New in Laravel 13.38. An application that reads from a replica and writes to the primary database has a well-known flaw: the replica lags a few seconds behind. A visitor saves their username, the page reloads… and shows the old one. The sticky option cannot help: it only applies to the request that wrote, and the redirect opens another one.
PreventStaleDatabaseReads
This middleware stores the time of the last write in the session. For a few seconds, the reads of this visitor go to the primary database; everyone else's stay on the replica.
use Illuminate\Foundation\Http\Middleware\PreventStaleDatabaseReads; Route::middleware(PreventStaleDatabaseReads::for(10))->group(function () { Route::get('/posts/{post}', [PostController::class, 'show']); Route::put('/posts/{post}', [PostController::class, 'update']); });
Without for(), the window lasts two seconds. The middleware needs a session, and only follows the default connection.
DB::usingWritePdo()
Without a session, for a webhook for example, you ask for the primary database for a block of code. Every read in the function goes there, loaded relations included, then the connection gets its setting back, even if an exception is thrown:
$order = DB::usingWritePdo(fn () => Commande::where('reference', $reference)->firstOrFail());
Your task
Here, the replica is a second SQLite file, copied only by hand (php artisan replique:synchroniser).
- In the preview, change your username: the page shows the old one. The replica lags up to five seconds behind. Make a visitor who just wrote read the primary database for five seconds.
- The payment provider calls
POST /api/webhooks/paymentless than a second after the order is created, and the order is not on the replica yet: the webhook answers 404. Make it read the order and its lines from the primary database.