Brewless Brewless Docs

Running your application

Handling peaks

Prepare an environment for a burst of requests, such as a ticket sale or a vote: replicas, PHP threads, the database, open connections.

On this page

A peak is a burst of requests that comes at a known moment: a ticket sale that opens at 10:00, a vote during a broadcast, a mailing. An environment that sleeps does not catch one cold. Prepare it before the moment, and give it back afterwards.

How much an environment can answer

Every replica of the web container runs FrankenPHP with two PHP threads per vCPU, and each thread answers one request at a time. Roughly:

requests a second ≈ replicas × threads per replica ÷ seconds per request

20 replicas of 1 vCPU have 40 threads. At 100 ms a request that is about 400 requests a second; at 1 s a request, 40. A request that waits on the database holds its thread while it waits, so the time a request takes is what decides it, more than the processor.

What a test environment did with a vote endpoint that stores each vote in a Serverless SQL Database before it answers (November 2026):

Set-up Offered Answered Median
20 replicas of 1 vCPU, a new database connection per request 500/s 184/s 6.3 s
The same, connections kept open 500/s 335/s 67 ms
20 replicas of 2 vCPU, connections kept open 500/s 492/s 99.9% accepted
From zero replicas, nothing prepared 1,000/s 7% in the first 10 s

The database itself stayed around 1 vCPU: the threads were the limit, not PostgreSQL.

Before the peak

  1. Start replicas in advance. A replica that starts during the peak makes the first requests wait for it. Raise web.min in brewless.yml and deploy, or set it in the console or with brewless scale, some minutes before the moment; see Scaling. Raise web.max too when the formula above says you need more.
  2. Give the replicas more processor. web.cpu: 2000 gives each replica 2 vCPU and so four threads instead of two; see brewless.yml.
  3. Boost the database. A Serverless SQL Database scales up as the load grows, from a minimum that is low unless you raised it. Plan a boost with time to warm up, so that a restart for a large raise happens before the peak and not during it: brewless db:boost production --min=4 --max=8 --for=2h --at=09:30. See Database capacity.
  4. Keep database connections open. Without it, every request opens a new TLS connection to the database first. See below.

Afterwards, put web.min back and let the boost end, or the replicas and the database keep costing what they cost during the peak.

Connections that stay open

With brewless/laravel 1.5 or later, the plain variable BREWLESS_DB_PERSISTENT keeps the PostgreSQL and MySQL connections open between requests:

brewless.yml
environments:
  production:
    variables:
      BREWLESS_DB_PERSISTENT: 'true'

A variable reaches the containers with the next deploy. Each PHP thread then keeps one connection, also while the container is quiet, so the number of connections is replicas × threads: 20 replicas of 2 vCPU hold 80. Keep that under what the database accepts. Scaleway gives a Serverless SQL Database more connections as it gets more vCPU, up to 1,000; an open connection does not keep it awake.

What the package takes care of:

  • A connection that an earlier request left in the middle of a transaction is rolled back before the next request uses it.
  • After the database restarted, for a boost, a failover or maintenance, the first query on an old connection fails as a lost connection and is tried again on a new one, for up to BREWLESS_DB_RETRY_SECONDS.
  • A setting of the session (SET …) stays with the connection and reaches the next request on that thread. Do not rely on one; on Serverless SQL sessions are shared anyway. See Databases.

A queue in between

Answering at once and storing the vote from a queued job feels faster, but the jobs still have to be stored by the same database, by fewer workers. In the test above it only paid off with more workers (worker.max) or with jobs that store many votes in one insert. Without that the queue grows during the peak and empties long after it.