This project is not covered by Drupal’s security advisory policy.
Drupal makes over a hundred strictly sequential Redis calls on an authenticated page request. On a single host nobody notices: a GET costs about 0.05 ms. Across an availability zone it costs about 0.6 ms, and those calls become the response time.
This module batches, memoises and reorders that traffic so the same work waits for the network less than half as often. It sends slightly more Redis commands than stock Drupal and waits far less. It is for deployments where the cache is a network hop away: AWS ElastiCache across availability zones, a managed Redis outside the cluster, or any topology where a cache read costs closer to a millisecond than to nothing. If your cache is on localhost, this module is not for you — and it says so honestly rather than claiming a saving it cannot make.
Features
Six independent changes, all aimed at the same thing. Each is switched on separately, so the module can be rolled out in stages and reverted by removing one line.
- Batched writes. All cache writes of a request, across every bin, go out as one pipeline after
fastcgi_finish_request(), off the critical path entirely. Repeated writes to a key are deduplicated and reads are answered from the buffer. - No redirect hop on render cache hits.
VariationCachereads a cache ID, gets aCacheRedirectnaming the real cache contexts, then reads again. That mapping is structural, so it is memoised in APCu and verified on use: a stale mapping degrades to a miss, never to wrong data. - Batched cache tag checksums. The redis backend issues a plain GET per single-tag checksum, about thirty per page request. The set of tags a request touches is nearly constant, so it is learned and fetched in one MGET. Checksums are still read fresh every request; only the batching changes.
- One round trip per lock. Release and renewal are compare-and-swap, done upstream with WATCH/GET/MULTI/EXEC. A Lua script does the same atomically in one round trip, and without leaving a dangling WATCH on a persistent connection if the process dies.
- One round trip per invalidation batch.
invalidateMultiple()costs a sequential HGET plus HSET per cache ID upstream. - Connection hygiene. Connect timeout, read timeout, retry interval, TCP keepalive and TLS. PHP's default read timeout is unlimited, so a connection dropped by a failover blocks the worker until the FPM request timeout — which is how a brief failover becomes an outage.
Nothing is cached across requests except facts that are structural and self-verifying. Cache tag invalidations are never deferred: they are the source of truth for consistency and always go out immediately.
The module also ships the measurement half of the work: an optional X-Redis-RTT response header reporting round trips, commands, time in Redis, database queries and buffer statistics for the request. Latency work that is not measured before and after is guesswork, and no standard Drupal profiler reports sequential network waits.
Measured on Drupal 10.6 — 400 nodes, 62 users, 26 blocks, 4 views, authenticated traffic with Dynamic Page Cache missing, 0.5 ms of injected latency per hop: TTFB p50 from 213.4 ms to 116.1 ms (-46%), round trips from 111.7 to 47.4 (-58%), time in Redis from 115.6 ms to 43.0 ms (-63%). With no network latency at all, ±0%: the saving is the cost of the latency, and it disappears with it.
Post-Installation
There is no administration UI and no configuration entity. Enabling the module on its own changes nothing: every optimisation is switched on from settings.php, because the cache backend has to be selectable before the service container exists.
The minimum configuration registers the module's namespace with the class loader, selects the fast client and points the default cache bin at the deferred backend; the shipped redis_rtt.services.example.yml carries the individual service overrides, each of which can be left commented out. The README in the repository has the exact lines to paste.
The status report at Administration > Reports > Status report shows which parts are active, so a half-finished configuration is visible rather than silent.
Additional Requirements
Recommended modules/libraries
The APCu PHP extension is strongly recommended. Without it the render cache redirect shortcut and the cache tag warm set still behave correctly, but nothing they learn survives the request, so they save nothing. The status report says so if APCu is missing.
Similar projects
Redis is not an alternative to this module but its dependency: this module extends the 2.x backend rather than replacing it, and every cache entry it writes has the same format, so nothing persists in an incompatible state if it is removed.
A search of Drupal.org for modules addressing Redis round-trip latency found no close match. Caching modules generally aim at what is cached; this one aims at how many sequential network waits it takes to read what is already cached.
Project information
- Project categories: Performance
- Ecosystem: Redis
- Created by thebrokenbrain on , updated
This project is not covered by the security advisory policy.
Use at your own risk! It may have publicly disclosed vulnerabilities.
