by kentonv | 2025-10-04 14:14:23+00:00
> Cap'n Web [1] is the first RPC system in a long time (as far as I know) that implements object references.

Cap'n Proto does it too, and has been around since 2013. We use it extensively it the implementation of Cloudflare Workers. Many people have joined the team, initially thought "what is this weird thing? Why don't we just use gRPC instead?", and then after a few months of using it decided it's actually a superpower. I'm planning to write more about this on the Cloudflare blog in the next couple months, probably.

(Cap'n Proto is itself based on CapTP, the protocol used in the E programming language.)

I never actually used COM nor CORBA, but my impression is there's a few reasons they didn't work where Cap'n Proto does:

1. Excessive complexity. CORBA is a monstrously large standard, covering not just protocol but also system architecture ("Object Resource Brokers").

2. Lack of asynchronous programming. CORBA calls would synchronously block the calling thread until the call completed. But when making calls over a network (rather than locally), it's much more important that you be able to do other things while you wait. CORBA added (extremely complex) asynchronous I/O support late in its life but few people ever used it.

3. Lack of promise pipelining. This sort of follows from #2 (at least, I don't know how you'd express promise pipelining if you don't have promises to start with). Without promise pipelining, it's incredibly hard to design composable interfaces, because they cannot be composed without adding a round trip for every call. So instead you end up pushed towards big batch requests, but those don't play well with object-oriented API design.

4. Poor lifecycle management. An object reference in CORBA was (I am told) "just data", which could be copied anywhere and then used. The server had no real way of being notified when the object reference was no longer needed, unless clients proactively told it so (but this was up to the app). Cap'n Proto ties object lifetime to connections, so when a connection is lost, all the object references held across it are automatically disposed. Cap'n Proto's client libraries are also designed to carefully track the lifecycle of a reference within the client app, so that as soon as it goes out-of-scope (GC'd, destructor runs, etc.), a message can be sent to the server letting it know. This works pretty well.

5. Bad security model. All objects existed in a global namespace and any client could connect to any object. Access control lists had to be maintained to decide which clients were allowed access to which objects. This is a bolted-on security mechanism that sounds simple but in practice is extremely tedious and error-prone, and often people would avoid it by implementing coarse-grained security models. Cap'n Proto implements an object-capability model, aka capability-based security. There is no global namespace of objects. To access one, you have to first receive an object reference from someone who already has one. Passing someone an object reference implies giving them permission to use it. This may at first sound more complicated, but in practice it turns out to map very cleanly to common object-oriented API design patterns.

As a result of all this, in Cap'n Proto (and Cap'n Web), you can pretty much use the exact same API design patterns you'd use in a modern programming language, with lots of composable objects and methods, and it's all safe and efficient.

(I'm the author of Cap'n Proto and Cap'n Web.)