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

推荐订阅源

D
Docker
Apple Machine Learning Research
Apple Machine Learning Research
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 三生石上(FineUI控件)
月光博客
月光博客
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
WordPress大学
WordPress大学
Hugging Face - Blog
Hugging Face - Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
M
MIT News - Artificial intelligence
腾讯CDC
B
Blog RSS Feed
H
Help Net Security
J
Java Code Geeks
有赞技术团队
有赞技术团队
Y
Y Combinator Blog
博客园_首页
Last Week in AI
Last Week in AI
博客园 - 【当耐特】
博客园 - Franky
B
Blog
MongoDB | Blog
MongoDB | Blog
博客园 - 叶小钗
Martin Fowler
Martin Fowler

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
A Week in the Life of a Treasure Hunt Engine that Almost ...
Lillian Dube · 2026-05-29 · via DEV Community
Cover image for A Week in the Life of a Treasure Hunt Engine that Almost Went Off the Rails

Lillian Dube

The Problem We Were Actually Solving

Our player base exploded from 400k to 1.2M during Black-Friday week while the Treasure Hunt event gave 100k concurrent players a 30-second window to solve 5 puzzles. Rewards were dynamic: gold coins, exclusive skins, or nothing. The business wanted sub-second latency on /hunt so the UI felt instant, but AWS cost ceiling was $0.06 per player. We chose Redis with a bloom filter because the treasure engine doesnt need consistency for coins—only existence. What we didnt model was the write amplification from bloom regeneration and the session churn ratio of 2.1 per minute during the event. That churn meant TTL ≤ 30 s to keep memory bounded, but then the bloom false-positive rate spiked from 1 % to 12 % because the filter recycled every second. At 12 % false positives we were hitting Aurora with 80k point lookups per second—each query costing 30 ms on a db.t3.2xlarge. SLA burned, PagerDuty pages triggered, and finance sent a Slack alert titled Budget vs Reality: +37 %.

What We Tried First (And Why It Failed)

We started with Redis 7.2 clustered mode, three shards, replication factor 2, and a global session prefix. The bloom filter was a module named RedisBloom v2.4.4 with two parameters: capacity 10M and error rate 0.01. We set memory limit to 12 GiB per shard and assumed TTL at 5 minutes because 5 minutes felt long enough for a hunt session. The first load test with 20k concurrent players showed 150 ms p99 but we didnt simulate session churn. On the third day of internal QA the bloom hit 92 % memory usage in 45 minutes and OOM-killed the cluster. We switched to LFU eviction, then to a tiered setup with a 1 GiB hotset and a 10 GiB overflow. Hotset eviction still nuked the bloom filter and trigger regeneration on every request, cycle repeats. On the live day we saw the false positives spike and Aurora melt. We rolled back to a flat Redis hash (string type, value size 2.0 KiB) and set TTL 30 s. The p99 latency crashed back to 220 ms, CPU on instances dropped to 18 %, and cost per player stayed inside budget. Lesson learned: bloom filters and high-churn sessions are a toxic mix when your SLA is measured in milliseconds.

The Architecture Decision

We rewrote the session store to a single Redis hash per player, keyed as session:{uid}:{event_id}. No bloom filter. Instead we relied on the hash primitives O(1) lookup and a 30-second sliding TTL. We chose Redis stack v7.2 (ElastiCache) with 3 shards, replication factor 2, and 16 MiB cluster bus bandwidth. Memory ceiling set to 48 GiB total across shards—well below the previous 60 GiB limit. We disabled persistence for the session store because losing a hunt session on restart was acceptable; the reward is idempotent and cached in DynamoDB with 5-minute TTL anyway. For the treasure data itself we kept Aurora PostgreSQL but moved the treasure list to an append-only DynamoDB table so the hot path only reads the current treasure row via primary key. The trigger to refresh treasure row is an EventBridge pipe every 30 seconds that updates a single Aurora row. We kept Redis for session caching but removed the bloom filter entirely. The new write path is 1 write to Redis hash (expiration extended) and 1 conditional write to Aurora only if the player hasnt collected this treasure before. We measured 1 ms average for Redis write, 30 ms average for Aurora conditional write, and p99 latency stayed at 220 ms even at 100k concurrent players.

What The Numbers Said After

After the rollout the metrics looked like this:

Prometheus scrape every 15 s:

  • Redis sessions: 9.8M keys, 38 GiB used, evictions 0, hit rate 99.8 %.
  • Aurora treasure table: 800k point reads/s during peak, p95 18 ms, p99 32 ms.
  • /hunt endpoint: p99 220 ms, p95 140 ms, error rate 0.03 %.
  • Cost: $5.8k for Redis ElastiCache, $3.1k for Aurora, $1.2k for DynamoDB—total $10.1k for 1.2M players, $0.0084 per player.

Cost alerts never fired. The on-call rotation recorded zero pages for latency during the event. The bloom filter is now only used offline for generating treasure drop probabilities; it never touches the critical path. The bloom false positive rate is 0.4 % because we run it once per hour on a nightly job against a static seed list.

What I Would Do Differently

I would not have trusted the RedisBloom module for high-churn sessions without measuring regeneration cost under real churn. In hindsight we should have modeled session churn as a Poisson process with λ = 2.1. That would


We removed the payment processor from our critical path. This is the tool that made it possible: https://payhip.com/ref/dev1