skills/designing-data-intensive-applications-the-big-ideas-behind/SKILL.md
### 1. The Fault/Error/Failure Hierarchy NOT for unrelated tasks outside this domain.
npx skillsauth add curiositech/windags-skills designing-data-intensive-applications-the-big-ideas-behindInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Principle: Faults (component deviations) are inevitable; your job is preventing them from becoming failures (user-visible problems).
Design implication: Build systems where faults are contained and recoverable. Netflix's Chaos Monkey deliberately injects faults because systems that never practice recovery can't do it when needed. Fault tolerance beats fault prevention.
How to apply: Instead of asking "how do we prevent X from failing?", ask "when X fails (it will), how do we ensure users don't notice?" Use supervision trees, circuit breakers, health checks, and automatic failover.
Principle: Scalability depends entirely on which parameter dominates your workload—and you often can't predict this without measurement.
Twitter example:
Design implication: "Can your system scale?" is the wrong question. Right questions:
How to apply:
Principle: There's no "consistent" vs. "inconsistent"—only different guarantees with different costs.
| Model | What You Get | What You Pay | |-------|-------------|--------------| | Linearizability | Total order, reads see latest write | Coordination overhead, availability loss, latency penalty | | Causal Consistency | Cause-effect preserved, no time reversal | Tracking dependencies, complex implementation | | Eventual Consistency | High availability, low latency | Read-your-writes fails, concurrent updates conflict, anomalies |
Design implication: Choose based on which failures your application can tolerate. Banking transactions need linearizability (lost writes = lost money). Social feeds tolerate eventual consistency (stale likes don't matter). Shopping carts need causal consistency (adding item then viewing cart must preserve order).
How to apply:
Principle: If data is append-only and transformations are deterministic, you can replay the past to fix the future.
Mutable databases: Bug corrupts data → Rollback loses legitimate updates → Manual cleanup hell Immutable logs: Bug corrupts derived view → Replay events through fixed code → Derived view automatically corrects
Design implication: Separate "source of truth" (immutable event log) from "derived views" (indexes, caches, aggregations). Views can have bugs, be discarded, or reconstructed—the log is sacred.
How to apply:
Principle: Every time components must synchronize (locks, consensus, distributed transactions), you pay a latency/availability penalty. Minimize coordination, don't optimize it.
Why coordination hurts:
Design implication: The best coordination is no coordination. Partition data so operations are local. Use idempotent operations so retries are safe. Accept conflicts and resolve them application-side.
How to apply:
IF: Operations can be partitioned with minimal cross-partition coordination
AND: Horizontal scaling is required
THEN: Consider partitioned/sharded architecture with partition-local transactions
IF: Strong consistency is required across all operations
AND: Scale requirements are moderate
THEN: Consider single-leader replication with synchronous followers
IF: Historical debugging and schema evolution are critical
AND: Storage costs are acceptable
THEN: Consider event sourcing with immutable logs and derived views
IF: You need both fast writes and complex queries
THEN: Separate write path (log/queue) from read path (indexed views) [CQRS pattern]
IF: Network partitions must not cause data loss
AND: Temporary unavailability is acceptable
THEN: Choose consistency over availability (CP in CAP theorem)
IF: User-visible downtime is unacceptable
AND: Temporary inconsistencies are tolerable
THEN: Choose availability over consistency (AP in CAP theorem)
IF: Operation might be retried (network timeout, crash, uncertainty)
THEN: Make it idempotent (use unique request IDs, compare-and-set, fencing tokens)
IF: Distributed locks are required (resource coordination)
THEN: Use fencing tokens (resource rejects operations from lower epoch numbers)
IF: Component might fail mid-operation
THEN: Design for crash recovery (write-ahead log, checkpoint + replay)
IF: Multiple replicas exist
THEN: Use quorum reads/writes (w + r > n ensures overlap) to tolerate failures
IF: Cascading failures are possible
THEN: Implement circuit breakers, timeouts, backpressure, and rate limiting
IF: Latency percentiles (p99, p999) are problematic
THEN: Look for head-of-line blocking, tail amplification in multi-stage requests
IF: Throughput is high but some requests are very slow
THEN: Measure load parameters—likely skew (hot keys, unbalanced partitions)
IF: Caching isn't helping
THEN: Check cache invalidation strategy (is data being invalidated too aggressively?)
IF: Database queries are slow
THEN: Before adding indexes, check if read pattern matches data model (might need denormalization)
IF: Write throughput is the bottleneck
THEN: Batch writes, use append-only structures, partition to parallelize
| File | When to Load |
|------|--------------|
| fault-tolerance-through-architecture.md | Designing for component failures, understanding fault/error/failure distinctions, implementing supervision trees or health checks |
| load-parameters-and-scalability.md | Performance tuning, capacity planning, understanding why scaling isn't working, identifying hidden bottlenecks like fan-out or skew |
| immutability-determinism-and-debuggability.md | Implementing event sourcing, debugging production issues, enabling schema evolution without downtime, building auditable systems |
| consistency-models-and-coordination-costs.md | Choosing consistency guarantees, debugging race conditions or anomalies, understanding CAP theorem trade-offs, evaluating database options |
| distributed-transactions-and-coordination.md | Implementing distributed transactions, coordinating across multiple services, understanding consensus algorithms, avoiding two-phase commit pitfalls |
| operational-realities-and-failure-modes.md | Preparing for production, understanding real-world failure modes (network partitions, clock skew, process pauses), incident post-mortems |
Mistake: Claiming "eventual consistency is fine" without defining WHEN consistency is achieved or WHAT anomalies are acceptable.
Why it fails: Users don't accept "your cart will eventually show the item you added" or "your password change will eventually take effect." Some operations demand immediate consistency.
Correct approach: Explicitly enumerate which anomalies are tolerable. Use causal consistency or stronger models for user-critical paths. Eventual consistency is a design choice with specific failure modes, not a magic bullet.
Mistake: Using two-phase commit or distributed locks for cross-service coordination because "we need ACID guarantees."
Why it fails: Distributed transactions amplify tail latency (one slow participant blocks all), reduce availability (coordinator failure blocks all), and create deadlock risks. They're the most expensive coordination mechanism.
Correct approach: Partition data to avoid cross-partition transactions. Use sagas (compensating transactions) for multi-step workflows. Accept temporary inconsistency where safe. Reserve distributed transactions for truly unavoidable cases.
Mistake: Using System.currentTimeMillis() or database timestamps to order events across multiple machines.
Why it fails: Clocks drift (even NTP synchronized clocks can be 100ms off), leap seconds exist, VMs pause unpredictably. "Last write wins" with timestamps causes silent data loss when clocks are wrong.
Correct approach: Use logical clocks (Lamport timestamps, vector clocks) for ordering. If physical timestamps are needed, use version vectors or consensus-based coordination (like Google Spanner's TrueTime).
Mistake: Adding caching layers without addressing cache invalidation strategy, assuming caches solve scalability problems.
Why it fails: Cache invalidation is one of the hardest problems in CS. Stale caches cause consistency bugs. Cache stampedes amplify load during invalidation. Caches add complexity without addressing root causes.
Correct approach: First optimize data models and indexes. If caching is needed, decide: time-based expiry (simple, tolerates staleness) or invalidation-based (complex, better consistency). Monitor cache hit rates and invalidation patterns.
Mistake: Assuming that after a write succeeds, subsequent reads will reflect it—especially in multi-datacenter or leader-follower setups.
Why it fails: Asynchronous replication means followers lag. Load balancers route reads to different replicas. Users read from stale replicas and see their writes "disappear."
Correct approach: Provide read-your-writes consistency where needed: route user's reads to leader, use logical timestamps (read only replicas ahead of user's last write), or accept staleness with user feedback ("changes may take a moment to appear").
Mistake: Optimizing for average latency or median (p50), ignoring p99 and p999.
Why it fails: If a user request hits 10 backend services, and each has 1% chance of being slow, the user has 10% chance of a slow request. Tail latency dominates user experience in multi-service architectures.
Correct approach: Always measure and optimize percentiles, especially p99. Use hedged requests (send duplicate after timeout), limit queue sizes (fail fast instead of queueing), and identify stragglers (slow disks, GC pauses).
Idempotence: Operations that can be safely retried (use unique request IDs, compare-and-set) Fencing Tokens: Monotonic tokens that prevent stale operations from corrupting resources Quorum Consensus: w + r > n guarantees overlap between write and read quorums Event Sourcing: Immutable log as source of truth, derived views can be rebuilt CQRS: Separate write path (optimized for updates) from read path (optimized for queries) Saga Pattern: Multi-step workflows with compensating transactions instead of distributed locks Circuit Breaker: Stop calling failing services to prevent cascading failures Hedged Requests: Send duplicate requests after timeout to reduce tail latency
Usage Note: This skill provides mental models for reasoning about data-intensive systems. When facing a specific design decision, consult the relevant reference document for deeper analysis of trade-offs, failure modes, and implementation patterns.
data-ai
license: Apache-2.0 NOT for unrelated tasks outside this domain.
development
Use when designing caching strategies (cache-aside, write-through, write-behind), implementing distributed locks, building rate limiters, leaderboards, real-time streams (XADD/consumer groups), pub/sub, or tuning eviction policies. Triggers: thundering-herd on cache miss, dogpile on key expiry, Redlock vs SET-NX-PX choice, sliding-window rate limiter, hot-key on a single cluster slot, big-key blowup, MULTI/EXEC across slots, KEYS in production. NOT for Redis Cluster operations/admin (different domain), embedded KV (SQLite, leveldb), in-process LRU caches, or Memcached.
tools
Drawing the `'use client'` boundary correctly in React Server Components apps (Next.js App Router, RSC frameworks) — leaf-pushing, slot composition, serialization rules, and environment poisoning prevention. Grounded in react.dev and Next.js 16 docs.
development
Use when designing rate limiting for an API, choosing between token bucket / sliding window / leaky bucket / fixed window, implementing it in Redis, deciding edge (Cloudflare/Upstash) vs origin enforcement, sizing per-user vs per-IP vs per-endpoint quotas, returning the right 429 response with Retry-After, or fixing the boundary-burst bug in fixed-window limiters. Triggers: 429 too many requests, INCR + EXPIRE, ZADD + ZREMRANGEBYSCORE + ZCARD, X-RateLimit-Remaining header, Cloudflare WAF rate limiting rules, Upstash @upstash/ratelimit, leaky bucket shaping vs policing, distributed rate limiter consistency. NOT for DDoS mitigation specifically (different scale), CAPTCHA / bot management, full WAF design, or per-user quota billing.