Comparisons
Ten pairs that get conflated in real conversations. Neither column wins — what decides is the requirement. Each record leads with the confusion, because the confusion is the reason the record exists.
Authentication vs AuthorizationServer sessions vs TokensORM vs Raw SQLOptimistic vs Pessimistic concurrencySynchronous vs Asynchronous communicationOffset vs Cursor paginationLocal (in-process) vs Distributed cacheMonolith vs MicroservicesHorizontal vs Vertical scalingAt-least-once vs "Exactly-once"
Local (in-process) vs Distributed cache
What people get wrong about this pair
They are treated as the same idea with different storage. They have different correctness properties: a local cache has as many versions of the truth as you have instances, and invalidating it means broadcasting to every process. Also, no cache is a default requirement — plenty of backends are correct and fast without one.
In-process cache
Use it when
Small, hot, rarely-changing data where per-instance staleness is acceptable — config, feature flags, reference lookups.
Shared cache (e.g. a Redis or Memcached tier)
Use it when
Data that must be consistent across instances, is too big to hold per instance, or must survive a deploy.
| Dimension | In-process cache | Shared cache (e.g. a Redis or Memcached tier) |
|---|---|---|
| Read cost | A memory access | A network round trip |
| Consistency across instances | None — N independent copies | One shared value |
| Invalidation | Needs a broadcast or a short TTL | Delete the key |
| Survives deploy | No — cold start every release | Yes |
| Capacity | Bounded by process memory; unbounded means a leak | Bounded by the tier, with an eviction policy |
| New failure mode | Divergent answers between instances | A dependency that can be down or slow |