500 GB in one weekend: Shipsidekick's move from Neon to ClickHouse Postgres, before and after

Contents
Shipsidekick sells a web app for warehouse, order and transportation management. Its founder, Sawyer Bateman, says the team used to shut its Neon database off every busy Monday, the day customers ship their weekend orders.1 In mid-July 2026 they started moving to ClickHouse Managed Postgres. The cutover took one weekend, and the Monday after was quiet.1
ClickHouse wrote this case study, so read the numbers with care. The path is common, though: start on a pay-as-you-go cloud database and grow until connections and memory hit the ceiling.
Three connection pools, not data volume, broke Mondays
The app runs on Vercel, with Prisma as the ORM and serverless Postgres from Neon underneath. A connection pool is a set of database connections opened in advance and lent to requests in turn. When every connection is lent out, new requests queue and eventually time out: the pool is exhausted. Once Vercel’s Fluid compute was on, every request went through three pools. Prisma keeps its own. Vercel asks for a second pg pool, handed to Prisma, so requests can share connections.12 Outermost sat Neon’s PgBouncer, advertised at 10,000 connections but shared with an unknown number of other customers.1
The three limits fought each other. However the team tuned them, Bateman says, either the Prisma pool or the Vercel pool ran out; removing a layer hit the limits of Neon’s PgBouncer instead. Past roughly 3,000 database connections the database went down every time.1 The case study does not say at which layer that count was taken.
The machine was maxed out too. By mid-2026 Neon ran 16 compute units with about 64 GB of RAM for close to $2,300 a month, CPU sat at 100%, and the cache hit rate was 30–35%. An urgent ticket filed during an outage got its first reply 38 hours later.1
Side by side, the cache hit rate moved most
The new instance has 16 vCPU, 128 GiB of RAM, 3.7 TB of storage and a single standby. Bateman accepted losing about a second of writes on failover for a lower price.1 Storage is NVMe attached to the same server as the database, and the service is still in beta.3 The gains in figure 1 have three sources:
- One pool instead of three. Every server bundles PgBouncer, so Shipsidekick removed the Vercel pools and connects straight to it. A wave of Shopify webhooks can push traffic to 10,000 requests a second, yet only 1 to 200 connections reach Postgres.1 The bundled PgBouncer takes up to 5,000 clients.4
- Twice the memory, so the hot data fits. The cache hit rate went from 30–35% to 99%.1 Part of that is simply a bigger box, not the new service.
- Faster queries follow from the first two. A one-month shipment query fell from 1 minute 20 seconds to about 6 seconds; on average, about 10x faster.1
The cost side is thinner. The case study says the pricing was “fantastic” and well under a $4,000–5,000 monthly PlanetScale quote, but gives no new bill.1 With twice the RAM, the new bill may not be below $2,300. What is clear is cost per unit of performance: roughly the same money now buys Mondays that stay up.
The move took a weekend; one index got in the way
The move had two steps: copy the data while Neon kept serving, then switch traffic over one weekend.
The tool was ClickPipes, which uses Postgres logical replication to send every write to the target in order.1 Before switching it on in Neon: every compute restarts, wal_level cannot go back from logical, and computes stop scaling to zero, which raises the bill.5 The pipe copies the schema, takes a parallel snapshot, then follows new writes with CDC (change data capture).4 About 500 GB, estimated at a day and a half, took 4 to 5 hours.1
The one stop: a cron job writes invoices in several transactions, replication caught it halfway, and the target’s partial unique index rejected a row. The team dropped the index, let the copy finish and rebuilt it; ClickPipes paused and resumed without losing data.1 CDC also skips most index and constraint changes, so those are created by hand before cutover.4 Better to drop risky unique indexes before the copy than to fix them mid-flight.
The guide’s cutover: set Neon read-only, compare row counts, reset sequences, repoint the app, and keep Neon for a rollback.4 Shipsidekick also removed the Vercel-side pools and finished on Sunday.1
Read-only agents can still eat half the CPU
Read replicas on the new service must match the primary’s size and price for now, so the team gave AI agents a read-only role on the primary. One agent ran a query nobody noticed for days and pushed CPU to 40–50%. The role now has statement and transaction timeouts, and a dedicated replica is planned.1
Signs it is time to plan a move
- Several stacked connection pools, and fixing one breaks another.
- CPU pinned at peak, low cache hits, hot data bigger than RAM.
- More compute units raise the bill, not the speed.
- Outage replies measured in days.
What to copy is the method: one pool, memory sized to the hot data, risky indexes out before the copy, cutover on the quietest weekend, timeouts on agent queries. Check the bill and the 10x against your own workload.
References
- How Shipsidekick replaced Neon with ClickHouse Managed Postgres for 10x faster queries and better reliability, ClickHouse Blog
- Efficiently manage database connection pools with Fluid compute, Vercel Knowledge Base
- ClickHouse Managed Postgres, ClickHouse Documentation
- Migrate from Neon to ClickHouse Managed Postgres, ClickHouse Documentation
- Replicate data to ClickHouse, Neon Docs
Comments
Anonymous comments appear after review; signed in with GitHub, X or Facebook, they appear at once. Your email stays private and is only used for reply alerts.
Comments couldn’t load. Try again later.