This Hacker News discussion delves into Cloudflare's new Cap'n Web RPC (Remote Procedure Call) system, a JavaScript/TypeScript library designed to simplify browser-to-web server communication. Key features include object capabilities and promise pipelining, aiming to make remote calls feel like local function calls while optimizing network round trips. A central point of fascination and contention is its unique .map() implementation, which uses a "record-replay" mechanism rather than executing JavaScript directly, leading to debates about its hackiness, potential "footguns," and comparison to C#'s expression trees.
Commenters explore the system's "schemaless" design (relying on TypeScript for API definition), implications for stateful servers and load balancing, N+1 query problems (especially when compared to GraphQL's DataLoader), streaming capabilities, and how it handles exceptions and security. While many praise its innovation and flexibility, particularly for web worker communication and its ability to abstract network complexity, others express skepticism about its "magic," potential for implicit issues (like side effects and conditional logic in map()), and its language-specific nature, questioning if it genuinely solves the "fallacies of distributed computing" or introduces new complexities. The author, KentonV, actively participates, clarifying design choices and future aspirations.
Cap'n Web: A New RPC System for Browsers and Web Servers
(mtrovo 2 days ago) The Cap'n Web library introduces a "record-replay" mechanism for array .map() operations, where client-side callbacks are executed once with placeholder values, and subsequent pipelined calls are recorded as instructions to be replayed on the server. This is described as both "fascinating and terrifying."
(mdasen 2 days ago) This approach is contrasted with C#'s Expression Trees, which allow code (lambdas) to be inspected and transformed (e.g., into SQL by Entity Framework) rather than executed directly, a feature JavaScript lacks natively.
(squirrellous 2 days ago) The discussion expands into C#'s comprehensive feature set (dynamic loading, ADTs, functional programming, reflection, expression trees) and its perceived niche use outside enterprise backoffices, despite being widely used.
(drysart 2 days ago) Concerns are raised about inherent limitations of the "execute it once" approach, particularly how conditional logic within a map() function might be silently ignored or lead to unexpected behavior due to placeholder values evaluating as truthy and coercing to [object Object].
(kentonv 2 days ago) Kentonv (the author) clarifies that the placeholder is an RpcPromise, preventing actual inspection or computation within the map() callback. TypeScript's type system helps prevent misuse. Parsing JavaScript ASTs from .toString() is deemed too complicated for a small library.
(samwillis 2 days ago) A similar "RefProxy" tracing approach is used in Tanstack DB for query DSLs, building an Intermediate Representation (IR) of queries. Kentonv suggests servers can provide their own operations library for remote computation, allowing flexibility without bloating the core protocol.
(btown 2 days ago) The potential for "side effects" within map() callbacks (e.g., count += 1) is identified as a "footgun," as these effects would only run once on the client during recording. It's suggested to rename .map() to rpcMap() for clearer developer intent, akin to React Hooks' use prefix.
(kentonv 2 days ago) The .map() method is explicitly special-cased to enable promise pipelining without extra network round-trips, unlike other functions with callbacks that would incur additional RPC calls. Supporting filter() using the same approach is seen as more challenging due to the need for computation on results.
(davexunit 2 days ago) The Cap'n Web system shares similarities with OCapN (Object Capabilities Network), including capability transfer and promise pipelining, but differs in its lack of out-of-band capabilities (SturdyRefs) and third-party handoffs, making it more suited for traditional client-server SaaS.
(prngl 2 days ago) Parallels are drawn to ML compilation libraries (TensorFlow, JAX, PyTorch) that use tracing to build computation graphs, effectively treating dynamic languages as frontends for DSLs to enable optimizations like fusing operations and delaying execution.
(thethimble 2 days ago) Challenges with deployment and handling flaky connections are discussed. Kentonv explains that after a connection loss (e.g., WebSocket reconnect), objects must be reconstructed from scratch. A blog post on design patterns for robust Cap'n Web applications is suggested.
(mpweiher 2 days ago) The author's statement that "RPC fits the programming model we're used to" is critiqued as "the gentle tyranny of Call/Return," arguing for expanding beyond composed function calls. Kentonv counters that RPCs (with async/await and pipelining) compose well and are easy to understand, arguing HTTP/REST for APIs was a misstep.
(cogman10 2 days ago) Concerns are raised about Cap'n Web's stateful nature impacting load balancing, server scaling, and potential DDoS risks, as persistent connections can burden specific servers. Kentonv clarifies that session state lasts for the WebSocket connection's lifetime or a single HTTP batch request.
(benpacker 2 days ago) The .map() trick is acknowledged but doesn't fully replace GraphQL for solving the N+1 problem in traditional databases without server-side optimizations (e.g., DataLoader pattern). However, for SQLite in Cloudflare Durable Objects, N+1 queries are less problematic.
(jensneuse 2 days ago) A GraphQL vendor emphasizes N+1 for nested lists, security through query plans/rate limiting, and federation (multiple sub-services) as key advantages GraphQL offers over Cap'n Web's current model. Suggests combining Cap'n Web with GraphQL federation.
(dimal 2 days ago) The "schemaless" nature (relying on TypeScript interfaces) is questioned regarding the benefits of well-defined schemas like tRPC and Zod offer for runtime type checking. Kentonv suggests using Zod for now and hopes for auto-generation of runtime checks from TypeScript types.
(ianbicking 2 days ago) Asks about streaming/generators and exceptions. Kentonv describes a Stream interface using RpcTarget and explains that exceptions are serialized and reject promises. Mentions that Cloudflare Workers RPC already supports standard ReadableStream/WritableStream.
(unshavedyak 2 days ago) Questions support for non-JS/TS backends (e.g., Rust). Kentonv suggests using Cap'n Proto for Rust backends with a proxy converting between Cap'n Web and Cap'n Proto.
(myflash13 1 day ago) Critiques Cap'n Web as "solving all the wrong problems," arguing that the industry is moving towards data sync solutions (ElectricSQL, Turso) for collapsing API boundaries. Argues against abstractions that hide network boundaries, preferring explicit handling of latency and failures.
(kentonv 1 day ago) Rejects JSON serialization criticism, noting browser's built-in JSON performance, and WebSocket's automatic compression for efficiency, despite his preference for binary protocols (having authored Cap'n Proto).