Skip to content

Add a router that allows for protobuf defined services#371

Open
Monkatraz wants to merge 1 commit intomainfrom
brn-river-protobuf-router
Open

Add a router that allows for protobuf defined services#371
Monkatraz wants to merge 1 commit intomainfrom
brn-river-protobuf-router

Conversation

@Monkatraz
Copy link
Copy Markdown
Contributor

@Monkatraz Monkatraz commented Apr 9, 2026

Why

For distributed versioned server use, using River is a bit challenging - it's hard to do migrations and in some repository setups it can be hard to share types.

However, River's protocol and transport is exceptionally well tuned for browsers, capable of multiplexing, bidirectional streaming, and session state.

If we allowed for protobuf, we solve the migration problems and type sharing while retaining all the advantages of River's transport.

What changed

Added a new export path via /protobuf that exposes basically an equivalent of /router. It has its own client, server, etc.

You use everything almost identically to how you use normal River. The main distinctions are:

  • You need a special client that understands decoding protobuf. In the future we can make it so a client negotiates this, and a typical client can connect. That will require some protocol adjacent changes so I'm leaving that out for now.
  • You don't need to do .rpc, .stream, etc. since the client knows the protobuf spec.
  • Call arguments to handlers are different and ofc. you don't need to declare schema.
  • Procedure handlers all have the same error type, borrowing the codes from gRPC.
  • Streaming procedures don't have nice features like reqInit.

Compared to normal River with Typebox, you lose:

  • typed errors
  • no codegen
  • expressiveness

What you gain is:

  • type safety without versioning
  • portability
  • maybe performance

Example:

// proto/greeter.proto
service Greeter {
  rpc SayHello(HelloRequest) returns (HelloResponse);
  rpc ServerStream(HelloRequest) returns (stream HelloResponse);
}
import { createProtoService, createServer, createClient, Ok, ProtoCodec } from '@replit/river/protobuf';
import { Greeter } from './gen/greeter_pb';

const ProtoService = createProtoService<AppContext, ParsedMetadata>();

const greeterSvc = ProtoService.define(
  Greeter,
  { initializeState: (ctx) => ({ callCount: 0 }) },
  {
    sayHello: (request, ctx) => {
      ctx.state.callCount++;
      return Ok({ message: `Hello, ${request.name}!` });
    },
    // serverStream left unimplemented -> returns UNIMPLEMENTED at runtime
  },
);

const server = createServer(transport, [greeterSvc], { context: myAppContext });
const client = createClient(Greeter, clientTransport, serverId);
const result = await client.sayHello({ name: 'World' });

A new codec has been added as well that allows a pure protobuf based transport without msgpacking most messages.

Versioning

We should have a new version but none of this afaik is breaking. Bundle sizes shouldn't increase either with tree shaking because the buf dependencies are isolated to imports from ./protobuf.

  • Breaking protocol change
  • Breaking ts/js API change

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@Monkatraz Monkatraz marked this pull request as ready for review April 9, 2026 21:04
@Monkatraz Monkatraz requested a review from a team as a code owner April 9, 2026 21:04
@Monkatraz Monkatraz requested review from daweifeng-replit and removed request for a team April 9, 2026 21:04
@Monkatraz Monkatraz force-pushed the brn-river-protobuf-router branch from 7a1d6f0 to 28a72ce Compare April 9, 2026 21:13
@Monkatraz Monkatraz force-pushed the brn-river-protobuf-router branch from 28a72ce to 0e2728f Compare April 9, 2026 21:28
@Monkatraz Monkatraz force-pushed the brn-river-protobuf-router branch from 0e2728f to 77d06bf Compare April 9, 2026 21:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant