惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
B
Blog
Stack Overflow Blog
Stack Overflow Blog
量子位
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tailwind CSS Blog
MongoDB | Blog
MongoDB | Blog
小众软件
小众软件
博客园 - 三生石上(FineUI控件)
Recent Announcements
Recent Announcements
U
Unit 42
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
腾讯CDC
D
DataBreaches.Net
Microsoft Azure Blog
Microsoft Azure Blog
G
Google Developers Blog
M
MIT News - Artificial intelligence
P
Proofpoint News Feed
罗磊的独立博客
L
LangChain Blog
V
Visual Studio Blog
雷峰网
雷峰网
aimingoo的专栏
aimingoo的专栏
宝玉的分享
宝玉的分享

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Cache Stale Data Issues
Lavkesh Dwivedi · 2026-06-18 · via DEV Community

Originally published on lavkesh.com


I recall one of the first design decisions for our payments platform, which was to deploy an in-memory cache for low-latency access to customer account balances. The architecture diagrams looked clean, with Go services using sync.Once-initialized maps in memory, bypassing the database for sub-millisecond reads. However, this approach worked as expected for only three months, until users started reporting inconsistent charges on receipts.

The problem surfaced at peak hours when concurrent updates to the same balance would overwrite each other. For instance, the account balance for user ID 12345 went from $1,200 to $850 to $1,200 again within seconds, leaving the cache in a state that defied the database of record. Engineers stared at the logs, baffled by the mismatch between transactions and cached values, because the team had not accounted for the fact that memory maps are not thread-safe by default in Go.

Debugging revealed the fundamental error: we were optimizing for speed without considering write-through guarantees. The cache treated concurrent requests as idempotent, which they were not. During a single user’s purchase flow, multiple goroutines could validate the balance, each reading a stale value from memory before any had a chance to commit updates. We had to shift to Redis with explicit lock keys and time-to-live settings, adding 4 milliseconds of latency but ensuring atomicity.

The cache also invalidated itself only when a change occurred, not when an upstream source updated. We discovered this when the accounting team reconciled overnight and adjusted balances based on fee settlements - the cache never reflected these updates until it expired naturally. To fix this, we had to implement message queues to broadcast invalidation events across all services. What started as a performance optimization became three nights’ worth of rewriting concurrency models.

This experience taught me two concrete lessons about distributed systems: first, that latency and consistency are a trade-off, not a checkbox; second, that in-memory solutions scale poorly in production when data flows through multiple planes. The original diagrams omitted the reality of cross-service communication, assuming all updates would flow through a single request path. They didn’t, and this oversight led to significant issues.

We eventually replaced the local cache with a Redis cluster and added circuit breakers to handle Redis failures gracefully. The change dropped read throughput by 30% but eliminated 90% of our support tickets related to balance discrepancies. Engineers now run load tests simulating out-of-order updates, which they didn’t before the incident, to ensure the system can handle such scenarios.

The real mistake wasn’t using in-memory storage but treating it as a production-ready solution without stress-testing its edge cases. The team had seen this pattern work in POCs but didn’t account for the messy concurrency of real user behavior. That six-hour debug session in the server room, where we traced race conditions line by line, remains the most expensive but valuable lesson in distributed design I’ve learned.

I keep a screenshot of the problematic cache code on my wall as a reminder: theoretical elegance is worthless if it breaks under real-world load. Production systems demand we question every assumption, even the ones that worked in benchmarks. This experience has stuck with me, and I often think about it when designing new systems.

The next morning after the fix, the team sat in the conference room with stale chai, Go code open on every screen, and a shared understanding that the most obvious optimizations often hide the hardest problems. My mother still asks why we can’t just 'make things fast like the old days.' I tell her that making things fast without making them correct is like boiling a pot on the stove and forgetting to check if the rice is cooked.

I recall that moment in the conference room, with the team reflecting on what we had learned. The experience was a hard lesson in the importance of considering all aspects of a system, not just the theoretical benefits of a particular approach. It’s a lesson that has stayed with me, and one that I try to apply to all my work.