- Cloudflare Durable Objects giải quyết cache stampede chỉ bằng ~8 dòng JavaScript, không cần Redis hay distributed lock.
- Rebuild Queues trên DO giảm send latency 70% (200ms xuống 60ms) và tăng throughput 12.5x (400 lên 5.000 msg/s).
- Per-key singleton routing biến "cached" và "inflight" thành hai trạng thái của cùng một object - loại bỏ toàn bộ bài toán lock lease.
TL;DR
Một bài viết trên InfoQ của Gabor Koos (28/1/2026) trình bày phát hiện đáng chú ý: cache stampede - hiện tượng "thundering herd" khi cache miss - có thể được giải quyết bằng một implementation đơn giản trên Cloudflare Durable Objects.
Giải pháp coi "in-flight computation và finished response là hai trạng thái của cùng một cache entry, được sở hữu bởi một per-key singleton." Không cần Redis, distributed lock, marker row hay polling - chỉ một Promise mà mọi caller cùng await.
Vấn đề Thundering Herd là gì?
Ở quy mô lớn, một API phổ biến thường xuyên gặp kịch bản này: một URL được cache hết hạn, hàng nghìn request đồng thời đổ vào origin, database bị quá tải, response time tăng vọt, và đội on-call phải thức đêm xử lý incident.
Các cách phòng chống truyền thống đều kéo theo độ phức tạp đáng kể:
Redis với SETNX-based lock - cần coordination infrastructure, quản lý lease, xử lý TTL
Singleflight trong application process - hoạt động trên single server nhưng fail khi load balancer phân tán request sang node khác
KV với in-progress marker - cần polling và tạo race condition tiềm ẩn trên chính marker
Durable Objects đơn giản hóa tất cả bằng "per-key singleton routing: mọi request cho cùng một key đều đến cùng một logical instance trên toàn cầu, và instance đó xử lý chúng tuần tự với shared memory state." Không cần lock vì coordination không còn cần thiết.
Ba đảm bảo cốt lõi của Durable Objects
Durable Objects cung cấp đúng ba thứ cần thiết để pattern này hoạt động:
Đảm bảo | Lợi ích |
|---|---|
Per-key singleton routing | Mọi request cho một object ID đều đến cùng instance, bất kể xuất phát từ đâu trên thế giới |
Shared in-memory state | Khác với stateless Worker, DO giữ in-memory state giữa các request - bạn có thể lưu một Promise trên |
Serialized execution | Request đến một DO được xử lý tuần tự, không cần explicit lock |
8 dòng code giải quyết Thundering Herd
Đây là toàn bộ logic cốt lõi:
if (!this.inflight) {
this.inflight = this.compute().then((response) => {
this.cached = response.clone();
this.inflight = undefined;
return response;
});
}
return (await this.inflight).clone();Cơ chế hoạt động: miss đầu tiên trigger computation và lưu Promise vào this.inflight. 999 request đến sau đều await chính Promise đó - không ai chạy lại computation. Khi Promise resolve, state chuyển sang cached và mọi request tiếp theo trả về ngay lập tức không cần tính toán.
DO storage cũng phối hợp tốt: get() trả về ngay với entry đã cache không cần context switch, put() hoàn thành ngay qua cache-first write - tầng persistence không làm chậm pattern.
So sánh với các giải pháp khác
Giải pháp | Cross-node dedup? | Coordination layer | Pattern gọn? |
|---|---|---|---|
In-process Promise singleflight | Không | Không | Một phần - fail cross-node |
Redis + distributed lock | Có | Lock service, lease, TTL | Có nhưng rất nặng |
KV eventually-consistent + marker | Yếu | Marker row + polling | Không |
Durable Objects / Akka / Orleans | Có qua routing | Không - singleton IS coordination | Có |
Ưu điểm so với Redis không chỉ là ergonomics: bạn "loại bỏ toàn bộ một danh mục distributed-systems problem (lock lease, lease renewal, lease handoff, lease expiry under partition) bằng cách loại bỏ lock."
Ai nên dùng ngay?
Pattern này phát huy hiệu quả khi duplicate work tốn kém và traffic pattern spike không đoán trước được:
Edge API phục vụ long-tail content - đa số URL ít traffic cho đến khi đột ngột viral
Aggregation endpoint tổng hợp response từ nhiều upstream service
Expensive integration - third-party API có rate limit, paid LLM inference, analytical query nặng
Cloudflare tự chứng minh bằng cách rebuild Queues trên Durable Objects: send latency giảm từ ~200ms xuống ~60ms (giảm 70%), throughput mỗi queue tăng từ 400 lên 5.000 message/giây (tăng 12.5 lần).
Giới hạn cần biết
Hot key bottleneck: Routing mọi request cho một key qua một owner tạo điểm serialization. Key cực hot có thể chạm throughput ceiling - đặc tính đảm bảo correctness cũng giới hạn performance.
Phụ thuộc actor runtime: Stateless Lambda + DynamoDB không thể replicate pattern này sạch sẽ; cần runtime kiểu actor như DOs, Akka, hoặc Orleans.
State reset khi hibernation: DO hibernate sau idle period, xóa in-memory state. Kết quả cần persist phải được ghi ra durable storage (DO storage, KV, R2).
Production cần nhiều hơn 8 dòng: Ví dụ đơn giản bỏ qua timeout, retry, eviction, error propagation, và memory constraint. Implementation thực tế cần code đáng kể hơn.
Không thay thế toàn bộ cache: Pattern chỉ xử lý miss-and-stampede window. Cache dài hạn vẫn cần dedicated cache tier.
Chưa battle-tested rộng rãi: Bài viết gốc lưu ý đây "primarily là design proposal, chưa phải recipe đã kiểm chứng." Production case study còn hạn chế.
Tiếp theo
Câu hỏi thú vị không phải là liệu mechanism có hoạt động không - nguyên lý cơ bản đã được Akka và Orleans chứng minh hơn một thập kỷ. Câu hỏi là liệu cộng đồng serverless-edge có adopt hay không, hay vẫn default sang Redis vì quen thuộc và tutorial đều chỉ vào đó.
Nếu Durable Objects tiếp tục deliver kết quả tương tự Queues speedup, adoption sẽ dịch chuyển: "cache stampede protection chuyển từ bài toán distributed-systems riêng biệt giải bằng Redis thành property bạn có miễn phí khi cấu trúc edge worker như per-key actor." Đó là đơn giản hóa kiến trúc đáng kể.
Nguồn: InfoQ - One Cache to Rule Them All, Cloudflare Durable Objects docs.

