mpyw/laravel-cached-database-stickiness
Keeps Laravel's read/write database stickiness alive across requests by caching it. After a write, later requests are routed to the primary connection for a set period, preventing stale reads from replicas when using read/write connection splitting.
mpyw/laravel-cached-database-stickiness solves a problem Laravel's built-in sticky flag can't: read-replica lag across requests. Laravel's sticky => true only forces the write PDO for the remainder of the current request. This package caches the fact that a write happened, so the next few requests also read from the primary until the TTL expires.
Minimum setup:
composer require mpyw/laravel-cached-database-stickiness — the service provider is auto-discovered. As of v2.2.1 the constraints accept Laravel through ^14.0 and CI covers PHP 8.5, so it will resolve on current and upcoming Laravel majors.config/database.php as you normally would:'mysql' => [
'read' => ['host' => ['replica-1', 'replica-2']],
'write' => ['host' => ['primary']],
'sticky' => true, // still required — the package extends this behaviour
'driver' => 'mysql',
// ...
],
array) and set a TTL roughly equal to your replica lag SLA.web group — in Laravel 11+ that's bootstrap/app.php via ->withMiddleware(...).Where to look first: the README is short and is the authoritative source for class names and config keys, then the package's service provider to see exactly what it decorates in DatabaseManager. First use case: a user saves a profile (write → primary), gets redirected, and the follow-up GET hits a replica that hasn't caught up and renders stale data. That redirect-then-read flow is exactly what this package fixes and is the fastest way to validate your install.
web-group registration is the sane default.useWritePdo() explicitly or wrap the follow-up read in the package's helper so the cached stickiness is set.array and disable stickiness in phpunit.xml, or test against SQLite with no read/write split. Assert on getReadPdo() vs getPdo() only in a dedicated integration test.^14.0) and the CI matrix (PHP 8.5). Upgrading from 2.2.0 is risk-free, but note that widened constraints mean Composer can now install this on an unreleased Laravel major before broad real-world validation; pin if that makes you nervous.SELECT-shaped writes, INSERT ... RETURNING executed via select(), and stored procedures that mutate data may not register. If writes go through those paths, set stickiness explicitly.array or null cache driver silently kills the feature — state won't survive the request. Same for a per-server cache when you run multiple app servers behind a load balancer.cache:clear and deploys drop all stickiness. Right after a deploy you're back to raw replica reads, which is precisely when you don't want stale reads. Consider a distinct cache store/prefix so routine cache flushes don't nuke it, and never share the key namespace between environments.DB::transaction().DB::connection('mysql')->getReadPdo() with ->getPdo(), enable DB::listen() to see which host served each query, and confirm config('database.connections.mysql.sticky') is actually true — forgetting that flag is the most common "it does nothing" report.How can I help you explore Laravel packages today?