Redis comes up in Acumatica performance conversations for a specific, narrow reason: PXCache is per-graph-instance and per-request, not a shared distributed cache across app servers, so anyone running a multi-server deployment who wants a value computed once and reused across servers — a rate limit counter, an external API response cache, a computed lookup table refreshed hourly — has nowhere native to put it. Acumatica ships no built-in Redis integration; this is entirely custom code you write and operate.
The actual problem Redis solves in this stack
PXCache solves "don't re-query the same row twice within one request." It does not solve "don't call this slow external API from every app server independently" or "share a computed value across all three app servers without hitting SQL Server every time." Those are the legitimate reasons to add Redis: a shared, fast, cross-process cache that outlives a single request and is visible to every app server in the farm.
What is worth putting in Redis, and what is not
- Good fit: external API responses with a natural TTL. A currency exchange rate fetched from an external service, a tax rate lookup from a fiscalisation provider, a shipping rate quote — data that is expensive or rate-limited to fetch and tolerates being a few minutes stale.
- Good fit: expensive computed aggregates refreshed on a schedule rather than per-request — a dashboard summary number recomputed every 15 minutes by a scheduled job and read frequently by many users in between.
- Bad fit: anything that must reflect the current transaction state. Inventory on-hand quantity, order status, account balances — these must come from Acumatica live. Caching transactional data in Redis reintroduces the exact staleness problem PXCache's per-request scoping was designed to avoid, except now it is shared staleness across every user instead of contained to one request.
- Bad fit: session state unless you have specifically designed for it as part of a load-balancer strategy (see the sticky-sessions post) — retrofitting Redis-backed session state into Acumatica's UI session model is a much larger undertaking than a simple cache-aside pattern and is not the usual entry point.
The pattern I actually implement
Cache-aside, from custom graph or webhook-handler code, using StackExchange.Redis as the client — nothing exotic:
public static class ExchangeRateCache
{
private static readonly ConnectionMultiplexer _redis =
ConnectionMultiplexer.Connect(ConfigurationManager.AppSettings["RedisConnection"]);
public static decimal GetRate(string fromCcy, string toCcy)
{
var db = _redis.GetDatabase();
var key = $"fx:{fromCcy}:{toCcy}";
var cached = db.StringGet(key);
if (cached.HasValue)
return decimal.Parse(cached);
var rate = ExternalFxProvider.FetchRate(fromCcy, toCcy); // slow call
db.StringSet(key, rate.ToString(), TimeSpan.FromMinutes(15));
return rate;
}
}
Note the static ConnectionMultiplexer — same principle as the HttpClient guidance in the memory-leak post: create one connection multiplexer per process and reuse it, never one per call, since it is designed to be a long-lived, thread-safe, multiplexed connection.
Wrap every Redis call in a try/catch that falls through to the live data source on failure. A Redis outage should degrade your integration to "always fetches live, a bit slower" — never to "throws an exception and blocks the user's transaction." I have seen a poorly wrapped Redis dependency turn a genuinely optional performance optimization into a hard outage dependency, which defeats the entire point of adding a cache in the first place.
TTL beats explicit invalidation for this use case
For the external-lookup and scheduled-aggregate use cases above, a short TTL (minutes, not hours) is simpler and safer than building explicit cache invalidation hooks into every place the underlying data changes. Explicit invalidation is worth the complexity only when staleness has real business cost and the write paths are few and well-known — for most Acumatica-adjacent caching needs, a TTL that is short enough to bound staleness to an acceptable window is the pragmatic choice.
Wrapping up
Redis has no native place in Acumatica — it is infrastructure you add for a specific, narrow job: sharing expensive, tolerably-stale computed or externally-fetched values across app servers. Never cache genuinely transactional data in it, reuse one connection multiplexer per process, and always fail open to the live data source if Redis itself is unavailable.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.