PlanetScale — One million connections¶
Summary¶
Liz van Dijk (PlanetScale, 2022-11-01) publishes the empirical anchor behind PlanetScale's "nearly limitless connections" claim that the 2021 Jarod Reyes RDS-vs-PlanetScale comparison post referenced without specifying. She benchmarks one million concurrent open connections against a PlanetScale database by fanning out from AWS Lambda — 1,000 Lambda worker functions × 1,000 connections each, constrained by the Lambda runtime's hard open_files=1024 + function_concurrency=1000 defaults — and reaches the target in under two minutes, holds it steady for ~5 minutes, then drains to zero. The post is load-bearing for two reasons: (1) it names the two-tier connection-pooling architecture (VTTablet connection pooling + PlanetScale Global Routing Infrastructure) as the structural answer to the serverless-scale connection-count problem, and (2) it canonicalises the memory-overcommit risk of naively raising MySQL's max_connections as the reason you can't just "turn the knob higher" on a standalone database.
The post is short (~600 words) but architecturally dense — it's the definitive benchmarked reference for the connection-scaling claim, and it's the first canonical wiki source for both the max_connections-as-memory-last-resort framing and the AWS Lambda 1,000×1,000 fan-out benchmark methodology. The PlanetScale architectural-substrate walk is a ~3-sentence recap pointing at prior posts (Global Routing Infrastructure, VTTablet connection pooling); the new material is the benchmark itself + the architectural framing around standalone-DB max_connections economics.
Key takeaways¶
-
Standalone databases allocate per-connection memory buffers, so
max_connectionsis an economic ceiling, not a performance optimisation. Liz van Dijk verbatim: "A standalone database relies heavily on its ability to compartmentalize memory use to provide the strong isolation guarantees we expect, so it needs to allocate certain memory buffers on a per-connection basis. The more connections we create, the less memory we have available for the overall buffer pool, and so MySQL comes with amax_connectionsvariable built in that acts as a 'last resort' safety measure." Canonical wiki framing: the knob isn't artificial — it's derived from the memory budget. Raising it without adding memory trades buffer-pool working set for connection slots, which slows the hot path by reducing cache hit rate. -
Raising
max_connectionsbeyond memory allocation is a crash risk, not a scaling win. "While it may seem harmless to raise this variable at first (you may not be approaching the instance memory limits quite yet), making MySQL live outside its means (i.e. overcommitting memory) opens the door to dangerous crashes and potential downtime, so this is not recommended." Canonical wiki framing of the memory-overcommit failure mode: MySQL connections allocate on-demand (per-session buffers, sort/join buffers, thread stacks); the total addressable memory is the sum across all connections, so a burst that lands every connection on a memory-heavy query at once can OOM the database even when average usage is fine. Themax_connectionsceiling is the hard cap that prevents the slow-burn overcommit scenario. -
Application-level connection pools are necessary but insufficient for serverless / edge. "many development frameworks offer built-in functionality like connection pools. Connection pools allow a bulk amount of connections to be established up front and for the application to queue up its database requests on that side. While that works really well as both a performance optimization and safety feature for the database side, application-side connection pools become a similarly challenging area when trying to scale a serverless stack." Canonical wiki framing: a serverless function is a fresh process with a fresh pool. Horizontal scale-out multiplies pools, not requests-per-pool. At 1,000 concurrent Lambda workers × N-connection pools, the aggregate connection count can trivially overwhelm MySQL's 16,000-connection ceiling even at modest per-worker pool sizes.
-
The architectural fix is a proxy tier that owns upstream connections. "To both safeguard and optimize connection management for MySQL, Vitess and PlanetScale offer connection pooling on the VTTablet level. This scales alongside your cluster, and also allows for connection requests to be queued up there when a sudden application scale-up starts sending queries from a very large amount of horizontally spawned processes. This keeps the underlying MySQL processes safe from a memory management standpoint, and allows you to keep adding workers as needed to scale the application." Canonical wiki framing: the patterns/two-tier-connection-pooling shape — application-tier pool for cold-start elimination + proxy-tier (VTTablet) pool for global admission control. The proxy enforces the MySQL memory budget once, centrally, rather than requiring every application worker to respect it independently.
-
PlanetScale adds a second proxy tier on top of VTTablet: the Global Routing Infrastructure. "In addition to that, PlanetScale's Global Routing Infrastructure provides another horizontally scalable layer of connectivity, which we put to the test recently to help us prepare for the broader rollout of our serverless driver." Two-tier pooling at the platform level: edge Global-Routing-Infrastructure pool (terminates client MySQL at the edge, backhauls to origin over warm long-held connections) + in-cluster VTTablet pool (caps per-MySQL-instance connections at the proxy). Each tier enforces its own budget; together they decouple client connection count from origin MySQL connection count.
-
Benchmarked ceiling: 1,000,000 concurrent open connections held for ~5 minutes. "We decided to put this to the test by running one million active connections on a PlanetScale database." Fan-out geometry: 1,000 Lambda workers × 1,000 connections each = 1M. Shape constraint from Lambda runtime: "by default, the Lambda runtime environment has a hard
open_fileslimit of 1024 and a function concurrency limit of 1000. As such, we configured our test to run a total of exactly 1000 'worker functions', each of which established exactly 1000 connections, so we could stay within the Lambda runtime limits." Canonical wiki datum: 1M is benchmarked, not a hard ceiling — "the target itself should be considered no more than an arbitrary number. After all, our architecture is designed to keep scaling horizontally beyond that point." -
Ramp time: ~2 minutes from 0 to 1M concurrent. "We were able to scale up to maintain a total of one million open connections in under two minutes." Ramp shape described as smooth rise → steady hold ~5 min → drain to zero. No per-tier latency deltas disclosed during the plateau — the benchmark is about connection-count, not query-latency under connection pressure.
-
Per-worker loop is deliberately minimal. Each Lambda worker: (1) opens a MySQL connection using
go-sql-driver/mysql; (2) sends one handshake-validatingSELECT; (3) waits on a rendezvous barrier for all 1,000 workers to finish establishing; (4) holds the connection open an extra few minutes before closing. Canonical wiki datum: the test measures connection-establishment + steady-state hold, not sustained query throughput. A 1M-QPS test would require a very different rig.
Systems / concepts / patterns surfaced¶
-
New systems: (none — all named systems have canonical pages: systems/planetscale, systems/planetscale-global-network, systems/vitess, systems/mysql, systems/aws-lambda).
-
New concepts (3):
- concepts/max-connections-ceiling — the MySQL
max_connectionsvariable as the last-resort memory-protection cap on concurrent connections. Derived from the database's memory budget, not an arbitrary number. Raising it without adding memory trades buffer-pool capacity for connection slots. - concepts/memory-overcommit-risk — the standalone-database failure mode where raising
max_connectionsbeyond the memory budget exposes the DB to OOM-induced crashes. Memory-overcommit makes average utilisation look fine while a burst of simultaneously memory-heavy queries can kill the process. -
concepts/lambda-fanout-benchmark — the AWS-Lambda-based fan-out methodology for benchmarking a target system's concurrent-client ceiling, working around the Lambda runtime's
open_files=1024+function_concurrency=1000caps by choosing per-worker fan-out to maximise aggregate concurrency while staying within runtime limits. -
New patterns (1):
-
patterns/two-tier-connection-pooling — application-tier pool (cold-start elimination) + proxy-tier pool (global admission control + memory-budget enforcement). The application-tier pool converts per-request handshake cost into per-process setup cost; the proxy-tier pool converts per-application-worker connection count into a capped per-database connection count. Vitess's VTTablet + PlanetScale's Global Routing Infrastructure are the canonical two-tier instance, with the Global Routing Infrastructure adding a third edge-terminating tier on top.
-
Extended:
- systems/planetscale-global-network — canonical 1M-concurrent-connections benchmark attribution + framing as the architectural substrate that enables "nearly limitless connections" scaling beyond a single VTTablet pool.
- systems/vitess — canonical VTTablet-as-central-pool framing with the benchmarked 1M ceiling as the empirical anchor. Complements the 2023 Harshit Gangal Connection pooling in Vitess post (which canonicalises the three-era VTTablet pool design) with the end-to-end scaling number.
- systems/mysql — canonical
max_connectionsframing as a memory-derived ceiling, not an arbitrary limit. First wiki citation of the memory-overcommit risk of naively raising the knob. - systems/aws-lambda — canonical wiki framing as the fan-out benchmarking harness for a downstream service. The runtime constraints (
open_files=1024,function_concurrency=1000) are load-bearing parameters of the test design. - concepts/connection-pool-exhaustion — extends with the empirical anchor (1M concurrent connections sustained) for the claim that PlanetScale's pool design avoids the exhaustion failure mode at serverless-scale client counts.
- concepts/global-routing-for-databases — extends with the benchmarked empirical anchor for the CDN-shaped connection-scaling claim.
- concepts/serverless-tcp-socket-restriction — extends with the 1M-benchmark as motivation for why the Serverless Driver (HTTP-over-PlanetScale-HTTP-API) is needed: even with headless TCP, serverless runtimes multiply pools, not requests-per-pool.
- patterns/cdn-like-database-connectivity-layer — extends with the benchmarked empirical anchor.
Operational numbers¶
- 1,000,000 concurrent open connections: PlanetScale sustained this against a single database in the benchmark (2022-11-01). Not a hard ceiling — "our architecture is designed to keep scaling horizontally beyond that point".
- 2 minutes: ramp time from 0 to 1M concurrent connections.
- ~5 minutes: steady-state hold duration before drain.
- 1,000 × 1,000: Lambda workers × connections-per-worker fan-out geometry.
- 1,024: AWS Lambda default
open_fileshard limit per function container — upper bound on per-worker connection count. - 1,000: AWS Lambda default per-function
concurrencylimit — upper bound on number of simultaneously-running worker functions without an account limit increase. - 16,000: MySQL / RDS
max_connectionsceiling cited in companion post sources/2026-04-21-planetscale-comparing-awss-rds-and-planetscale — 62.5× below the benchmarked PlanetScale ceiling. - go-sql-driver/mysql: the Go MySQL driver used by the per-Lambda-worker test program.
- Per-worker loop: open connection → send validating
SELECT→ rendezvous barrier → hold open for a few minutes → close.
Caveats¶
-
Benchmark does not measure sustained query throughput under the 1M-connection plateau. The test opens + holds connections + sends one handshake-probe query per worker. Query latency / throughput / per-query CPU / tail latency during the plateau are not disclosed. A "1M concurrent connections" architecture is distinct from a "1M QPS" architecture; the post measures only the former.
-
Shard-count / replica-count / origin MySQL instance-count elided. The post says "a PlanetScale database" — the number of underlying Vitess shards and MySQL instances carrying the 1M connections is not disclosed. A single-instance 1M-connection claim and a sharded 1M-connection claim are architecturally very different; the post is ambiguous. Given Vitess architecture, the benchmarked database is almost certainly sharded (or at minimum has multiple replicas), but the numbers are not given.
-
Lambda fan-out introduces its own concurrency shape. Lambda workers don't all spin up in the same millisecond; the 2-minute ramp is likely dominated by Lambda's own cold-start / concurrency scale-up behaviour, not PlanetScale's connection-acceptance rate. The test measures how quickly the combined system (Lambda fan-out + PlanetScale's acceptance pipeline) reaches 1M concurrent, not how quickly PlanetScale alone can accept 1M connections. A test harness that pre-created the Lambda function instances or used a simpler load generator would give different ramp numbers.
-
"One handshake-probe query per worker" is the entire query load. This is an intentional design choice to isolate the connection layer, but it means the benchmark says nothing about query routing / VTGate planning / MySQL-primary write capacity under the plateau. Query-layer components may have been essentially idle during the hold.
-
2022-11-01 article, fetched 2026-04-21: 4-year gap. The 1M figure is now mid-tier by 2026 PlanetScale scales — the Serverless Driver launch (2022-08-18, two months earlier) is the contextual motivator; subsequent product evolution (Metal 2025-03, Portals 2024-04, HTTP/3 Fall 2024) extends the architecture further, but this post remains the canonical first publication of the benchmarked connection ceiling.
-
"Under two minutes" to ramp + "few extra minutes" on the plateau is qualitative. The post has one graph (connections-over-time) but no second-by-second transcription in prose. Exact ramp rate, plateau duration, drain rate are not given.
-
"Sign up to try it out"-voice: product pitch closing line + generic "PlanetScale's architecture is different" framing in the intro. Architecture density ~60–70% of a short body (most of the non-benchmark text is memory-management + pool-architecture recap that is canonicalised elsewhere on the wiki). Clears Tier-3 bar on the strength of the empirical benchmark anchor that the 2021 Reyes post named without specifying.
-
Liz van Dijk byline: Van Dijk is not one of the canonicalised "deep-internals" PlanetScale voices (Dicken / Francis / Barnett / Coutermarsh / Reyes / Raju / Gage / Gomez / Lien / Ekechukwu / Kukic / Morrison II / Noach / Gangal / Lambert / Taylor / Sougoumarane / Sigireddi / Guevara / Burlacu / Lord); she authors from the developer-advocacy / product-marketing angle (see her byline on multiple PlanetScale positioning posts). The post clears Tier-3 not on byline but on content: a benchmarked empirical anchor that multiple other ingested posts cite.
Source¶
- Original: https://planetscale.com/blog/one-million-connections
- Raw markdown:
raw/planetscale/2026-04-21-one-million-connections-53dd3ef5.md
Related¶
- systems/planetscale-global-network — the architectural substrate the benchmark validates.
- systems/vitess — VTTablet is the in-cluster pool tier; this post adds the 1M empirical anchor to the existing three-era pool-design canonicalisation.
- systems/mysql — the standalone-database
max_connectionsarchitecture this post positions PlanetScale against. - systems/aws-lambda — the benchmark harness; runtime constraints (
open_files=1024,function_concurrency=1000) are load-bearing test-design parameters. - sources/2026-04-21-planetscale-comparing-awss-rds-and-planetscale — Jarod Reyes 2021 post that references "1M concurrent connections" without specifying; this post is the spec.
- sources/2026-04-21-planetscale-connection-pooling-in-vitess — Harshit Gangal 2023 post canonicalising the VTTablet pool design; sister-disclosure at internals-altitude.
- sources/2026-04-21-planetscale-introducing-the-planetscale-serverless-driver-for-javascript — Taylor Barnett 2022-08-18 Serverless Driver launch; this post (2022-11-01, ~2.5 months later) is explicitly framed as preparation for "the broader rollout of our serverless driver".
- concepts/max-connections-ceiling / concepts/memory-overcommit-risk / concepts/lambda-fanout-benchmark — new canonical concepts introduced here.
- patterns/two-tier-connection-pooling — new canonical pattern introduced here.
- patterns/cdn-like-database-connectivity-layer — the sibling pattern the Global Routing Infrastructure is an instance of.