Build1 publisher2 min readPublished
Neki's router plans the shard before Postgres plans the query
Neki puts a fleet of connection-owning routers in front of sharded Postgres, each emitting a topology plan you can read with EXPLAIN (NEKI_PLAN). Sessions live on the router holding them, so losing one is visible to the client.
The Engineer · Build desk

What happened
- Neki gives every query two plans: the router uses the data topology to choose shards and decide how results are combined, then Postgres plans execution on each shard the router selected.
- A fleet of routers sits between the application and Postgres and keeps client connections inside its own processes, so a client connection no longer requires a Postgres backend process.
- The authors say the router becomes the application's Postgres endpoint, which removes the need for a separate PgBouncer layer in front of the database.
- A Neki sidecar beside each Postgres instance takes planned work over gRPC and forwards it on a pooled connection, without parsing or planning the SQL itself.
- EXPLAIN (NEKI_PLAN) on a query filtering one user_id returns Route [EqualUnique] with the shard key as bind parameter $1, against an orders table sharded on user_id using xxhash.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- exposure A router failure takes its sessions with it, so the application's reconnect path absorbs the failover rather than the database.
- capability Connection handling and distributed query processing can be bought by adding routers, without touching the shard count or the Postgres instances underneath.
- decision Anyone already running a pooler has to decide whether to hand the endpoint to a component that also parses SQL and holds the session state.
- cost Every Postgres instance gains a sidecar to deploy, version and monitor, so the per-shard operational footprint grows with the shard count.
The router replaced the literal 42 with $1 and marked user_id as a bind parameter, so one cached plan serves every user_id and the value goes into xxhash at run time [16]. It also rewrote the statement it forwards, adding the public schema qualifier [17]. Planning cost is paid once per statement shape. The rewrite is worth knowing about before you go hunting for your own SQL in a Postgres log.
The sidecar beside each Postgres instance does not parse or plan the SQL it is handed; it forwards the work on a pooled connection and streams the response back to the router [13]. Parsing, splitting statements into per-shard work and coordinating results all run on the router fleet, and the authors, Andres Taylor, Harshit Gangal and Ahmed Darwich, say this matters most for complex joins and aggregations, where the SQL sent to each shard can look very different from the original query [11][20]. Adding routers therefore buys connection capacity and distributed query processing from the same pool [8].
They call the routers operationally stateless: no durable application data, and a cached data topology, table definitions and query plans that can all be rebuilt, which they say is what makes routers easy to add, resize or remove [6]. The same write-up says the router owns and preserves client session state [12], and that if a router fails, the sessions connected to it are lost [7]. Both hold at once. Fleet capacity is cheap to change and a session is not portable, so I would start any evaluation with the driver's reconnect behaviour.
The case for the design rests on process-per-connection: every direct connection requires a backend process on the instance it reaches, those processes consume memory, and large process counts add scheduling overhead [2]. The authors call that a bottleneck for applications that want thousands of client connections [3]. The post does not report measurements, neither a per-backend memory figure nor router throughput [21]. Two things have to hold for the trade to pay in a given deployment. Your client connection count has to exceed what your Postgres instances can host as backends. And enough of your query mix has to span shards to justify a component that plans, because a single-shard read like the example is one Route with no aggregating or reordering on the way back [18].
Debugging gains a second surface. One query now has two plans to read, the router's via EXPLAIN (NEKI_PLAN, FORMAT TEXT, COSTS FALSE) and Postgres's via a regular EXPLAIN on the selected shard [1]; in the example the second one returned an index scan using orders_pkey [19].
What to watch
- Published per-connection memory and router throughput figures would let a team size a fleet instead of estimating.
- The plan vocabulary beyond EqualUnique: what the router emits for cross-shard joins and aggregations, and whether those plans cache the same way.
- Whether a later version keeps a session alive across the loss of the router that owns it.