Archive: SYSLUME's earlier technical-decision work. Current focus: AI agents for SME back-office work → Order Intake

Performance Decision Guide

Redis vs Database Optimization: What Should You Fix First?

By SYSLUMEUpdated 13 September 20263 min read

A decision guide for choosing between cache introduction and fixing the underlying database path.

SYSLUME Decision Library · 3 min read · Engineering judgment, not generic best-practice lists

“Add Redis” is often a diagnosis failure

When latency rises, caching is attractive because it can reduce database work quickly. But if the dominant problem is an inefficient query, missing index, lock contention or an oversized synchronous transaction, a cache can hide the symptom while increasing invalidation and consistency complexity.

First classify the bottleneck

SignalFirst investigationRedis likely?
Repeated identical read-heavy queriesQuery frequency + freshness toleranceOften
Slow unique queriesExecution plan, indexes, data modelUsually not first
Write contentionTransaction scope, locks, hot rowsRarely the core fix
Expensive computed result reused broadlyRecompute cost + invalidation modelOften
Session/rate-limit ephemeral stateConsistency and expiry needsGood fit

The cache tax

A cache introduces key design, invalidation, TTL policy, stampede handling, memory pressure, observability and degraded-mode behavior. Count that operational cost in the decision matrix instead of treating Redis as “free speed”.

Decision sequence

  1. Measure the hot path and identify what consumes time.
  2. Fix obviously inefficient database work first.
  3. Estimate the theoretical gain from caching the repeated work.
  4. Define freshness and invalidation requirements.
  5. Load-test both the happy path and cache-miss/stampede path.
Change-my-mind condition: if optimized database work still cannot meet the target and the workload has repeatable, freshness-tolerant reads, the case for Redis becomes materially stronger.

Calculate the ceiling before adding infrastructure

Synthetic arithmetic, not a benchmark: assume an average request takes 200 ms, of which 120 ms is eligible repeated database work. At an assumed 80% hit rate and 5 ms cache lookup on every request, the simplified average becomes 80 + 5 + (0.20 × 120) = 109 ms. This excludes network variation, serialization, invalidation, misses under load and other costs.

If eligible work is only 20 ms, the same assumptions produce 180 + 5 + (0.20 × 20) = 189 ms. The theoretical gain is now small. Neither calculation predicts p95 or p99: averages and tail latency are different quantities.

Before decidingRecord
Database contributionMeasured request spans, plans, row estimates and actual work
FreshnessMaximum tolerated stale data for this operation
Cache failureLoad on the database during cold start and cache outage
Exit conditionTarget latency and error rate under a reproducible load

A useful next experiment

Measure one representative read path on a safe test workload. Inspect its query plan, correct the highest-impact inefficiency, then repeat the same workload. Only compare the cache option after defining hit-rate and freshness assumptions. Keep the original dataset, workload shape and configuration with the result.

Source and interpretation

PostgreSQL's EXPLAIN documentation explains plans and estimates. EXPLAIN ANALYZE executes the statement; use a suitable test environment. The illustrative latency arithmetic above is SYSLUME's model, not a PostgreSQL or Redis performance claim.