CONCEPT Cited by 1 source
Shared-nothing PHP request model¶
Definition¶
The shared-nothing PHP request model is PHP's foundational language-runtime design decision that every HTTP request executes in a fresh PHP process image, with no state carried across requests. At the end of every request, PHP tears down the interpreter state, releases all file handles, closes all database connections, and returns to a clean slate.
This is a language-runtime property, not a framework choice — it predates Laravel, Symfony, WordPress, and every modern PHP framework by 20+ years. It was a deliberate simplifying assumption from PHP's early web-origins: each request is independent; the web server forks / runs CGI / uses FPM to dispatch a fresh PHP interpreter; when the request is done, the interpreter exits.
Canonical statement¶
"PHP, by design, shares nothing across requests. This means at the end of every request, PHP will close the connection to the database."
— Matthieu Napoli, PlanetScale blog, 2023-05-03 (Source: sources/2026-04-21-planetscale-serverless-laravel-applications-with-aws-lambda-and-planetscale)
What "shared nothing" eliminates¶
- Connection pools across requests — a PDO connection opened on request N does not survive to request N+1. Any application- level "connection pool" lasts for at most one request.
- Compiled template caches — Blade / Twig templates recompile (or re-load-from-disk) per request unless a framework-specific opcache is configured.
- Parsed config / route-table / service-container state —
Laravel's service container boots per request; the
configuration cache files
bootstrap/cache/config.phphelp reduce the cost but the container graph still re-resolves. - Authentication / authorization caches — user record, policy cache, role resolution all re-hit the DB unless explicitly session-cached.
The opposite: persistent-process runtimes¶
Most modern web stacks have persistent-process request models:
- Node.js — one Node process, event loop handles thousands of requests, DB connections live for the process lifetime.
- Python ASGI (FastAPI, Starlette) — one ASGI app instance, async event loop, persistent DB pool.
- Ruby Puma — worker processes serve many requests each.
- Go
net/http— single process, goroutine per request, shared DB pool. - Java Spring Boot / servlet containers — single JVM, thread pool, persistent Hibernate session factories and DB pools.
All of these amortise expensive setup (DB connection, TLS handshake, ORM bootstrap, framework wiring) across many requests. PHP's shares-nothing model pays that setup cost on every request.
How classic PHP hid the cost¶
In a traditional PHP deployment (LAMP stack, nginx + php-fpm),
persistent database connections were the folk workaround —
mysqli_pconnect() / PDO's PDO::ATTR_PERSISTENT => true instruct
the PHP-FPM worker process to keep the DB connection open in the
worker's own process memory between requests, even though the
user-visible PHP execution context is torn down. The trick works
because PHP-FPM pre-forks worker processes that persist across
requests; the process stays alive, only the PHP execution context
resets. A fixed pool of FPM workers × persistent connections =
bounded DB connection count.
This is the LAMP-era "pool" — it's implicit, tied to the FPM worker pool shape, and only works when requests actually land on the same FPM worker process repeatedly.
Why serverless breaks the LAMP workaround¶
On AWS Lambda via Bref, the LAMP persistent-connection trick doesn't work the same way:
- Each Lambda invocation is a fresh execution environment in the worst case (cold start). No FPM worker to keep connections around in.
- Even warm Lambda execution contexts are isolated per-concurrent- invocation. 50 concurrent requests = 50 Lambda execution environments, each with its own fresh PHP state.
- PDO persistent-connection caching within one Lambda context
is bounded by
BREF_LOOP_MAX. Without explicit opt-in, every invocation pays the full setup cost.
The TLS handshake against PlanetScale (2-3 RTT over encrypted TLS) is the dominant per-request cost because: - PlanetScale requires SSL (no plaintext). - Query time is ~0.3 ms. - Handshake is ~10-50 ms. - PHP bootstrap + Laravel boot is ~20-60 ms.
Canonical benchmarked result: p50 75 ms under classic shares-nothing
Bref, vs p50 14 ms with Laravel Octane
which keeps the PHP process + DB connection warm across
BREF_LOOP_MAX = 250 invocations. (Source:
sources/2026-04-21-planetscale-serverless-laravel-applications-with-aws-lambda-and-planetscale.)
Why the constraint is architecturally interesting¶
Shares-nothing PHP is a counter-example to the "stateless good, stateful bad" simplification. Stateless per-request process boot is conceptually pure — easy to reason about, trivially horizontally scales — but it can't amortise setup costs across requests. In a world where setup is cheap (~1 ms), the tradeoff is fine. In a world where setup is expensive (TLS handshake, ORM bootstrap, service-container resolution), the tradeoff costs 5× latency.
The fix is selective persistence via Octane / Swoole / RoadRunner / FrankenPHP: keep the expensive parts (DB connections, compiled routes, service container) alive across requests, reset the cheap-to-reset parts (request scope, session, auth guard) per request. The programmer accepts a narrow window of cross-request state-leak risk in exchange for a large latency amortisation win.
Related concepts¶
- concepts/ssl-handshake-as-per-request-tax — the single largest cost of shares-nothing PHP against a TLS-terminated database. Canonical quantitative demonstration against PlanetScale.
- concepts/connection-pool-exhaustion — shares-nothing PHP makes the client-side connection-pool-exhaustion story worse because every invocation is a fresh pool. The fix is either server-side (patterns/two-tier-connection-pooling) or client-side (patterns/persistent-process-for-serverless-php-db-connections).
- concepts/cold-start — shares-nothing compounds cold-start cost because there's no warm context to reuse.
Seen in¶
- sources/2026-04-21-planetscale-serverless-laravel-applications-with-aws-lambda-and-planetscale — canonical introduction of the shares-nothing-PHP-meets- serverless problem. Matthieu Napoli: "PHP, by design, shares nothing across requests." Benchmarked 5.4× p50 improvement from switching to Octane persistent mode.
Related¶
- systems/php — language runtime
- systems/laravel — framework built on shares-nothing base
- systems/laravel-octane — persistent-process handler that escapes the model
- systems/bref — Lambda PHP runtime
- systems/aws-lambda — serverless target
- concepts/ssl-handshake-as-per-request-tax — the cost multiplier
- concepts/connection-pool-exhaustion — aggravated by shares-nothing
- concepts/cold-start — compounded by shares-nothing
- patterns/persistent-process-for-serverless-php-db-connections — the fix
- patterns/two-tier-connection-pooling — server-side complement