Data topologies solve the routing problem in sharded systems by decoupling logical schemas from physical placement. This allows engineers to scale PostgreSQL horizontally while maintaining a single-database experience and optimizing performance through data colocation.
“Vitess for PostgreSQL” is a useful shorthand for the ambition behind Neki, but it significantly understates the architecture we have built. Neki carries forward what we learned from Vitess in a new sharding architecture designed around PostgreSQL’s internals and semantics from the start.
PlanetScale has spent years building and operating Vitess at scale. That experience has shaped how we approach query routing, data placement, and the challenge of making many database servers behave like one.
We have previously written about how Neki makes hundreds of database servers behave like one. Here, we take a closer look at the mechanism that controls where data lives and how queries are routed.
One of Neki’s core design goals is flexibility in data placement. There are many ways engineers need to map their logical database schemas onto physical shards in order to optimize for performance and scalability.
That configuration is expressed as a data topology.
Sharding spreads data across multiple servers, but it also creates a unique routing problem. How does each query find the shard or shards that hold the data it needs?
Without a routing layer, the application would need to keep track of where its data lives and choose the correct shard for each query.
A data topology is how Neki answers that question. It is a JSON configuration that describes a PostgreSQL sharding scheme by mapping logical PostgreSQL tables to groups of physical shards and giving routers the information they need to route queries.
A data topology has three building blocks:
Together, these building blocks tell Neki how to route queries.
The data topology does not provision or manage physical shards. Those shards are provisioned separately, and the topology refers to each one by a stable ID. In Neki, a shard consists of a PostgreSQL primary and its replicas.
Consider a store database that partitions related data around its customers.
CREATE TABLE customers (
customer_id bigint PRIMARY KEY,
name text NOT NULL,
address text NOT NULL
);
Suppose the customers table needs to be distributed across two shards. Here's how a data topology might look:
The topology names this shard index customer_id_xxhash. It tells Neki to convert each customer_id into a routing key using xxhash.
Neki supports three shard-index strategies:
xxhash.Each strategy takes a different path from customer_id to a physical shard:
In this example, customer_id is the shard key, and its value is 42. Each strategy transforms its value into a different routing key. xxhash produces 0x2e4fe982b68910ac, which falls in the range assigned to customer-shard-1. modulo calculates 42 mod 4, producing 2, which falls in the range assigned to customer-shard-2. range uses 42 directly, which falls in the range assigned to customer-shard-1. In each case, the shard group selects the physical shard whose range contains the routing key.
The customer_data shard group divides the possible xxhash results between two shards. This example focuses on hash-based routing, but shard groups work similarly with modulo-based and range-based strategies. Key-range boundaries are written as hexadecimal prefixes, so 80 expands to 0x8000000000000000, the midpoint of the routing space:
customer-shard-1: 0x0000000000000000 through 0x7fffffffffffffff
customer-shard-2: 0x8000000000000000 through 0xffffffffffffffff
For example, these two customer IDs land on different shards because their hashes fall in different ranges.
customer_id 42 → 0x2e4fe982b68910ac → customer-shard-1
customer_id 1 → 0xf36b4a1a44f78bf3 → customer-shard-2
Neki first hashes the raw customer ID, then finds the range containing the resulting routing key.
Every data topology also names an authoritative group, a single-shard home for database-wide metadata such as sequences and schema information. Queries against customers still use customer_data.
The databases section follows the familiar PostgreSQL hierarchy of databases, schemas, and tables.
Most tables do not need to appear in the data topology. An unlisted table inherits the default shard group from its schema, then its database, then the cluster, allowing a topology to shard an entire database with one default and list only the exceptions.
Put together, the explicit entry for store.public.customers maps it to customer_data, where it uses the customer_id_xxhash shard index and the group’s key ranges.
On one side of a Neki router is the user's application, speaking the PostgreSQL wire protocol. On the other, the application's data can be spread across an ever-growing number of physical shards.
The data topology connects the two, informing the router how data is divided and which shard or shards should receive a query. The result is a live configuration that maps logical databases to physical locations. Neki updates it during resharding, table moves, and imports, all while the application continues serving traffic.
From here, we can explore the rest of Neki’s architecture and how it helps make 768 servers look like 1.
Running PostgreSQL at scale? Request access to Neki.
Continue reading on the original blog to support the author
Read full articleNeki solves the scaling limits of single-instance Postgres without sacrificing compatibility or forcing application-level sharding. It provides a managed path to horizontal scaling with online operations, making it easier to handle massive workloads while keeping standard Postgres tools.
Understanding sharded query lifecycles is essential for engineers scaling relational databases. It reveals the trade-offs in query routing and aggregation necessary for high-performance distributed systems.
Neki enables Postgres to scale horizontally by decoupling connection management and query routing from the core engine. It allows developers to use standard drivers while transparently handling sharding, complex distributed queries, and high connection counts.
Large tables in Postgres create systemic risks, from vacuum bloat to transaction ID wraparound. Understanding how to mitigate these through partitioning or sharding is critical for maintaining high-availability systems as data scales beyond the limits of vertical hardware.