Skip to content
ESC

Searching...

Quick Links

Type to search • Press to navigate • Enter to select

Keep typing to search...

No results found

No documentation matches ""

Session locking.

Serialize requests that share one session so overlapping requests cannot overwrite each other's session data.

Jul 13, 2026

Session locking runs requests that share one browser session one at a time, so two requests cannot overwrite each other's session data.

What this does

A browser session holds short-lived state between requests: validation errors, old form input, and the page a member meant to reach after signing in. When two requests share one session id and overlap, a second tab, a fast double-click, or a slow save that runs alongside a quick one, the later request can save a stale copy of the session and drop what the first one wrote.

With session locking on, requests that share a session id run in sequence. Requests from different members stay parallel, so one busy member never slows another. The token-based Agent API does not use sessions and is not affected.

Session locking protects session data. It does not change flash's one-request lifetime, so a value you need to survive longer than the next request belongs in the session or the database, not in flash.

When to use it

Most installations never hit this race. It takes one member firing two requests against the same session at the same moment, from a second tab, a double-click, or a slow save that overlaps a quick one. Loyalty points and other records stay safe either way, since they are database transactions, not session state. What a race can drop is short-lived session data: a validation message, or half-typed form input.

Existing installations do not need to turn this on. Leave it off unless you see the symptoms: a form that loses its validation errors, input that vanishes on submit, or a member sent back to sign in with no clear cause. If that happens, follow the steps below. Turning it on is a short maintenance step, not an emergency.

New installations turn it on during setup, because the database is already there to back it and the installer checks it for you. There is no cost to the protection from the first day.

During installation

A fresh installation needs no extra setup for this. The installer writes session locking on by default and points it at the database you configure during setup, so there is no separate store to install or tune. As part of the install it runs a live check that the database can take and release a lock. When the check passes, installation continues and locking is active from the first request. When the database cannot back the lock, the installer stops with a message that names the cause, instead of finishing into a broken state.

In normal use nobody notices any of this. Locking affects two requests that share one session and overlap, and lets everything else run as before.

Turning it on for an existing installation

Session locking needs an atomic shared lock store. Add these to your .env:

SESSION_BLOCK=true
SESSION_BLOCK_STORE=database
SESSION_BLOCK_LOCK_SECONDS=45
SESSION_BLOCK_WAIT_SECONDS=60
  • SESSION_BLOCK_STORE must be database or redis. The database store needs the cache and cache_locks migration, which ships with Reward Loyalty. Never use file, a file store cannot coordinate across web workers.
  • SESSION_BLOCK_LOCK_SECONDS is the lease one request holds. Keep it above your longest web request and your PHP max_execution_time.
  • SESSION_BLOCK_WAIT_SECONDS is how long a second same-session request waits for the lease. Keep it at or above the lease.

Apply the change:

php artisan config:cache
php artisan session:preflight

Then reload PHP-FPM or your workers so the new config takes effect. Run the change during a maintenance window.

The session:preflight command reports one of three states. session:preflight returns success when locking is off, so it never fails an update on an installation that has not opted in.

  • Off: locking is disabled. Preflight passes.
  • Healthy: locking is on and the lock store answered a live acquire-and-release check.
  • Critical: locking is on but the lock store is unusable. Fix the store before you serve traffic, or set SESSION_BLOCK=false until it works.

What can go wrong

  • The lock store is not reachable. Preflight reports critical. Correct the database or redis connection, or turn locking off, before you reload workers.
  • A lease is too short. A request that runs longer than SESSION_BLOCK_LOCK_SECONDS can lose its lease to the next same-session request. Keep the lease above your slowest request. The self-update no longer runs long work inside a session request, so it stays well under the lease. See Updating.
  • You set the store to file. A file store cannot serialize across workers. Preflight rejects it.

Where to check status

The Health center shows whether session locking is on and whether its lock store is healthy, alongside the other application checks. An installation that has not opted in shows locking as off, which is a healthy state, not a warning.

Cookies on this site.

Google Analytics runs only if you allow it. Cookie policy