Redis is an outstanding tool for caching: fast, efficient and well understood. AWS ElastiCache takes it further by handling scaling and minor version upgrades with very little management overhead.
But in a distributed environment, managing the connections is as important as the caching itself, and that is where the cost quietly accumulates.
The tension is straightforward. Slow responses hurt user experience and revenue. An over-provisioned Redis deployment hurts the infrastructure bill. Every connection to a remote Redis instance adds latency, and at volume those milliseconds add up into something a customer can feel.
The question worth asking first
The useful question turned out not to be “how do we make Redis faster”. It was: how stale can this cached data afford to be before it is worth another network request to refresh it?
That is a business question disguised as a technical one, and the answer differs per key. Once you can answer it, a large proportion of requests do not need to reach Redis at all.
The proxy
I built a Redis proxy that sits in front of the instance and intelligently filters requests, serving cached responses locally where the staleness budget allows. Intercepting queries and answering them without a round trip removes the connection entirely for those requests — saving the latency and reducing load on Redis at the same time.
Beyond simple filtering, the proxy holds persistent connections and supports request pipelining. Fewer network round trips, better throughput, and less connection churn for Redis to manage.
The second-order effect matters as much as the first. By cutting the number of direct connections, Redis itself has more capacity left for the operations that genuinely need it, so the same instance size goes further.
What it gave back
Faster responses for users, lower infrastructure cost, and a caching layer that scales without simply buying a bigger instance.
The pattern generalises. A cache is a decision about acceptable staleness, and a proxy is where you get to encode that decision once rather than scattering it through the application. Most of the performance was not in doing the work faster — it was in establishing which work did not need doing.