Stream Processing Engine System Design Template
Stream processing engine: event time, watermarks, windows and triggers, late data, keyed state, barrier checkpoints, exactly-once sinks, backpressure, rescaling
Cara menggunakan: Use it when designing or reviewing a stateful streaming platform or a large streaming job. Fill the capacity inputs (event rate, keys, lateness, checkpoint interval) first, because state size and recovery time decide the cluster shape. The main pitfall is promising exactly-once end to end when only the state is exactly-once; choose idempotent upserts or transactional sinks per output.
Pratinjau
System Design: [Stream processing engine name]
Reference design for a distributed stream processing engine that runs long-lived, stateful jobs over unbounded event streams. It covers event time versus processing time, windows, watermarks, triggers and late data, keyed state with periodic checkpoints, exactly-once state with transactional sinks, backpressure and rescaling. The concepts follow the Dataflow model (Akidau et al., PVLDB vol. 8 no. 12, 2015) and asynchronous barrier snapshots (Carbone et al., 2015); the text and the worked design are original. It follows the structure of the System Design Document template. Replace every
[bracketed]value and every row marked Example.
Document control
| Field | Value |
|---|---|
| Document ID | [SDD-SPE-001] |
| System / feature | [Stream processing engine for real-time aggregation] |
| Version | [0.1] |
| Status | [Draft / In review / Approved / Implemented / Superseded] |
| Owner | [@owner] |
| Author(s) | [@author] |
| Reviewers | [@reviewer-1], [@reviewer-2] |
| Last updated | YYYY-MM-DD |
| Classification | [Internal] |
| Delivery guarantee | [Exactly-once state; exactly-once or idempotent output per sink] |
| Related | Message Queue System Design (system-design/design-message-queue), CDC Pipeline System Design (system-design/design-cdc-pipeline), Data Pipeline Specification (ai-data/data-pipeline-spec) |
Approvals
| Role | Name | Decision | Date |
|---|---|---|---|
| Tech lead | [@name] | [Approved / Changes requested] | YYYY-MM-DD |
| Staff / principal engineer | [@name] | [Decision] | YYYY-MM-DD |
| SRE / operations | [@name] | [Decision] | YYYY-MM-DD |
| Data platform owner | [@name] | [Decision] | YYYY-MM-DD |
| Security | [@name] | [Decision] | YYYY-MM-DD |
Revision history
| Version | Date | Author | Change summary |
|---|---|---|---|
| 0.1 | YYYY-MM-DD | [@name] | First draft for design review |
| 0.2 | YYYY-MM-DD | [@name] | Example: Moved from processing-time to event-time windows after the replay incident |
| 0.3 | YYYY-MM-DD | [@name] | Example: Added unaligned checkpoints for jobs under sustained backpressure |
| 1.0 | YYYY-MM-DD | [@name] | Example: Approved |
Contents
1. Overview
1.1 Problem statement
[Example: Product teams compute campaign metrics (impressions, clicks, spend per campaign and country per minute) with a nightly batch job and a fragile set of consumers that count in memory. Dashboards are 12 hours stale, counts change after every consumer restart, and mobile events that arrive late (devices offline, then reconnecting) are either dropped or counted in the wrong minute. Advertisers dispute numbers that do not match the batch reports.]
1.2 Proposed solution
[Example: A shared stream processing engine runs declarative jobs that read partitioned event logs, assign each event to event-time windows, keep per-key state in an embedded log-structured store on local SSD, and take a consistent distributed snapshot every 30 s by injecting barriers into the streams. Watermarks track event-time progress per source partition; triggers emit early speculative results every 10 s, an on-time result when the watermark passes the window end, and corrections for late events for up to 10 minutes. Sinks either commit transactionally on checkpoint completion or write idempotent upserts keyed by window. Jobs rescale by restoring a savepoint with a different parallelism; state moves in key groups.]
1.3 Decisions requested from reviewers
| ID | Question | Recommended option | Section |
|---|---|---|---|
| Q-01 | Example: Event time or processing time for business metrics? | Event time with heuristic watermarks | 7.1 |
| Q-02 | Example: How long do we accept late events? | 10 minutes allowed lateness; later events to a side output | 7.2 |
| Q-03 | Example: Checkpoint mechanism? | Aligned barrier snapshots, unaligned when backpressured | 7.3 |
| Q-04 | Example: Exactly-once to sinks? | Two-phase commit for log sinks, idempotent upsert for databases | 7.4 |
| Q-05 | Example: Checkpoint interval? | 30 s, bounded by freshness for transactional readers | 3.4, 7.4 |
| [Q-nn] | [Question] | [Option] | [Section] |
1.4 45-minute interview path
| Minutes | Cover | Output on the whiteboard |
|---|---|---|
| 0 to 5 | Clarify the use case: what is aggregated, freshness target, how late events can be, correctness expectation | Core requirements FR-01 to FR-05, NFR-01 to NFR-04 |
| 5 to 10 | Estimate ingest, state size and recovery time | Parallelism 64, ~25 GB state, recovery of a few minutes |
| 10 to 20 | Draw sources, coordinator, workers, state backend, checkpoint storage, sinks | Diagram in section 6 |
| 20 to 35 | Deep dive: pick event time and watermarks (7.1) plus checkpoints and exactly-once (7.3, 7.4); if the interviewer leans on correctness of late data, use 7.2 instead | Barrier and two-phase commit sequence |
| 35 to 42 | Backpressure, rescaling, hot keys | Key groups, credit-based flow control |
| 42 to 45 | Trade-offs and what changes at 10x | Table in section 10 |
2. Requirements
2.1 Core functional requirements
| ID | Requirement | Priority |
|---|---|---|
| FR-01 | Example: Read events from partitioned logs and write results to logs, key-value stores and an analytical store | Must |
| FR-02 | Example: Group events by key and assign them to tumbling, sliding and session windows by event time | Must |
| FR-03 | Example: Emit early, on-time and late results per window as configured by a trigger | Must |
| FR-04 | Example: Keep per-key state across restarts with no loss and no double counting | Must |
| FR-05 | Example: Stop a job with a savepoint and restart a new version or parallelism from it | Must |
| FR-06 | Example: Route events later than the allowed lateness to a side output for audit | Should |
| FR-07 | Example: Join two streams by key within an event-time interval | Should |
| [FR-nn] | [Requirement] | [Must / Should / Could] |
2.2 Non-functional requirements
| ID | Quality | Target | Measured as |
|---|---|---|---|
| NFR-01 | Throughput | Example: 2 million events/s per job at peak | Source lag stays flat during load test |
| NFR-02 | Freshness | Example: p99 of 60 s from event arrival to visible on-time result | End-to-end marker events |
| NFR-03 | Correctness | Example: Final window values equal a batch recomputation over the same input | Daily reconciliation job |
| NFR-04 | Recovery | Example: Output fresh again within 5 minutes after a worker loss at peak | Chaos drill |
| NFR-05 | Isolation | Example: One job's backpressure does not slow another job | Multi-tenant load test |
| [NFR-nn] | [Quality] | [Target] | [Measurement] |
2.3 Below the line (out of scope)
- [Example: A SQL interface for ad-hoc queries; jobs are defined in code or the pipeline format in 4.2 for this release]
- [Example: Ingestion from devices; the engine reads from the existing message logs (
system-design/design-message-queue)] - [Example: Machine-learning feature serving; results land in stores that a feature service reads]
- [Example: Exactly-once delivery to external HTTP endpoints that offer no idempotency key]
- [Item deferred, with the release that will take it]
3. Capacity estimation
3.1 Assumptions
| Input | Symbol | Value | Source |
|---|---|---|---|
| Peak events per second (one large job) | Example: 2 000 000 | Source log metrics x growth | |
| Average event size | Example: 1 KB | Sampled payloads | |
| Events per second one stateful task handles | Example: 40 000 | Benchmark of the window operator | |
| Active keys (campaign x country) | Example: 5 million | Last 30 days | |
| Window size and allowed lateness | , | Example: 1 min, 10 min | Product requirement |
| Window state per key and window | Example: 100 B | Measured | |
| Deduplication horizon and ID size | , | Example: 600 s, 16 B | Source retry behaviour |
| Checkpoint interval | Example: 30 s | 7.3 |
3.2 Ingest and parallelism
Consequence: the keyed shuffle moves roughly the same 2 GB/s (16 Gbit/s aggregate) across the network on top of ingest, so worker network interfaces (Example: 25 Gbit/s) are sized for ingest, shuffle and checkpoint upload together, and the job is split into at least 64 parallel tasks from day one. The maximum parallelism (number of key groups) is fixed at 1 024 so the job can grow 16 times without rehashing state.
3.3 State size
Open windows per key are one current window plus the lateness horizon:
Total keyed state is about 25 GB, or about 0.39 GB per task at parallelism 64. Consequence: deduplication, not the windows, dominates state, so it gets its own TTL and is the first thing to shrink (shorter horizon or idempotent producers upstream). State lives in an embedded log-structured store on local SSD rather than on the heap, which keeps garbage collection pauses away from the watermark path and enables incremental checkpoints.
3.4 Checkpoints and recovery
With Example 20% of state changing per interval, each incremental checkpoint uploads 5 GB, or about 167 MB/s sustained to object storage. Consequence: checkpoint upload is a steady background load that must be budgeted in network capacity, not an occasional burst.
After a worker loss the job rewinds to the last checkpoint. Worst-case backlog is one interval plus detection and restore time:
Spare capacity is events/s, so catching up takes about s. Consequence: recovery to fresh output is under 3 minutes at peak, which meets NFR-04 but not a 60 s freshness promise during incidents; raising headroom to 1.5x or shortening the interval are the two levers.
3.5 Output
Each of the 5 million keys emits one on-time row per minute, about 83 000 rows/s, plus early firings every 10 s (up to 500 000 rows/s if every key is active). Consequence: sinks must accept batched upserts, and early firings are enabled only for keys a dashboard actually reads.
3.6 Summary
| Quantity | Estimate | Design consequence |
|---|---|---|
| Ingest | 2 GB/s (16 Gbit/s aggregate) | Worker NICs sized for ingest + shuffle + checkpoints; shuffle sized like ingest |
| Parallelism | 64 tasks, 1 024 key groups | Rescale up to 16x without rehashing |
| Keyed state | ~25 GB (dedup 19.2 GB) | Embedded LSM store on SSD; TTL on dedup state |
| Checkpoint upload | ~167 MB/s | Incremental checkpoints; network budget |
| Recovery | ~3 min to fresh at peak | Meets NFR-04; more headroom if freshness tightens |
| Output | 83 000 to 500 000 rows/s | Batched upserts; early firings opt-in |
4. API design
4.1 Control plane API
| Method and path | Purpose | Notes |
|---|---|---|
POST /v1/jobs | Submit a job definition and artifact | Idempotency key header; returns job ID |
GET /v1/jobs/{id} | Status, parallelism, last checkpoint, lag | |
POST /v1/jobs/{id}/savepoints | Take a savepoint, optionally stop the job | Returns savepoint URI |
POST /v1/jobs/{id}/rescale | Restart from a savepoint with new parallelism | Bounded by max parallelism |
POST /v1/jobs/{id}/upgrade | Deploy a new version from a savepoint | State compatibility checked first |
DELETE /v1/jobs/{id} | Cancel a job | Savepoint taken unless force=true |
4.2 Pipeline definition
A job declares what is computed, where in event time, when results are emitted and how refinements relate (the four questions of the Dataflow model, paraphrased):
job: campaign-metrics
version: 14
source:
log: ad-events
timestamp_field: event_time
watermark:
strategy: bounded_out_of_orderness
max_delay: 30s
idle_partition_timeout: 60s
key_by: [campaign_id, country]
window:
type: tumbling
size: 1m
allowed_lateness: 10m
trigger:
early: every 10s processing_time
on_time: at_watermark
late: every_element
accumulation: accumulating # each firing carries the full value so far
aggregate: {impressions: count, clicks: count, spend_micros: sum}
dedup: {field: event_id, horizon: 10m}
late_side_output: ad-events-too-late
sink:
type: upsert_store
table: campaign_minute
key: [campaign_id, country, window_start]
checkpoint: {interval: 30s, mode: aligned, unaligned_after: 60s}
4.3 Output record
Every emitted result states which firing it is, so consumers can tell a speculative value from a final one:
{"campaign_id": "c-7781", "country": "VN", "window_start": "2026-10-22T09:41:00Z", "window_end": "2026-10-22T09:42:00Z", "impressions": 18240, "clicks": 311, "spend_micros": 9120000, "pane": {"timing": "LATE", "index": 3, "is_last": false}, "watermark": "2026-10-22T09:42:31Z"}
4.4 Errors
| Status | Problem type | When |
|---|---|---|
| 409 | state-incompatible | Upgrade changes a stateful operator's ID or state schema without migration |
| 409 | rescale-out-of-bounds | Requested parallelism exceeds max parallelism |
| 422 | invalid-pipeline | Window, trigger or watermark settings contradict each other |
| 503 | checkpoint-in-progress | Savepoint requested while the previous one is still running |
5. Data model
5.1 Entities
A key maps to a key group by hash modulo max parallelism; key groups map to tasks in contiguous ranges. Rescaling moves whole key groups, never single keys, which keeps state handles coarse.
5.2 Storage choices
| Data | Store | Key | Why |
|---|---|---|---|
| Job and version metadata | Example: Relational database | job_id, version | Small, audited, transactional |
| Leader and checkpoint pointer | Coordination service (system-design/design-distributed-lock-coordination) | jobs/{id}/leader, jobs/{id}/latest-checkpoint | Leader election and an atomic pointer swap |
| Live keyed state | Embedded LSM store on local SSD per task | (key_group, key, namespace) | Fast local reads and writes; large state |
| Checkpoint files | Object storage | /{job}/{checkpoint_id}/{operator}/{handle} | Durable, cheap, shared files across incremental checkpoints |
| Input and output streams | Partitioned log | Partition by key | Replayable from offsets |
5.3 Access patterns
| Access pattern | Served by | Partition key and rationale |
|---|---|---|
| Update window state for one event | Local LSM, key (key_group, campaign_id, country, window_start) | Key group from the business key, so all events for a key reach one task |
| Fire all windows ending before the watermark | Event-time timer queue per task, ordered by timestamp | Timers stored with the key group, so they move with state on rescale |
Check duplicate event_id | Local LSM, key (key_group, campaign_id, country, event_id) with TTL 10 min | Key group from the business key, so deduplication runs in the same task as the window; it inherits that key's skew (7.5) |
| Find the latest completed checkpoint | Coordination service pointer | One small value per job, updated atomically |
| Restore state for key groups 0 to 15 | Checkpoint metadata lists handles per key-group range | Range layout lets a task fetch only its ranges |
| Read results for a dashboard | Sink table keyed (campaign_id, country, window_start) | Upsert target; idempotent by construction |
6. High-level design
| Component | Responsibility | Scales by |
|---|---|---|
| Job coordinator | Schedules tasks on workers, restarts on failure, one active per job | Leader election; one per job |
| Checkpoint coordinator | Triggers checkpoints, collects acknowledgements, publishes the completed pointer | Part of the coordinator |
| Source tasks | Read partitions, extract timestamps, generate watermarks | Source partitions |
| Window and dedup tasks | Keyed state, timers, triggers | Key groups |
| Sink tasks | Buffer output, pre-commit and commit per checkpoint | Output partitions |
| Object storage | Checkpoint and savepoint files | Managed service |
7. Detailed design
7.1 Deep dive: time, watermarks and progress
Processing time is when a worker sees an event; event time is when it happened. Mobile and retried events arrive minutes late, and a replay after an outage delivers hours of events in minutes, so grouping by processing time puts events in the wrong window and makes results depend on when the job ran.
| Option | How it works | Strength | Weakness |
|---|---|---|---|
| A. Processing-time windows | Window by arrival clock | Simple; no lateness logic | Wrong under replay and delay; not reproducible |
| B. Event time with perfect watermarks | Source guarantees order (for example a single ordered log) | Exact completeness | Rarely available for real sources |
| C. Event time with heuristic watermarks | Watermark = max event time seen minus a bound, per source partition | Works on real data; tunable | Some events arrive behind the watermark (late) |
| D. Event time, no watermarks, fire on processing-time triggers only | Periodic emissions of running totals | Fresh | Never knows when a window is complete |
Choice: C, with per-partition watermarks combined by taking the minimum across inputs at every operator. Reason: it produces reproducible results under replay and a clear point at which a window is considered complete, while triggers (7.2) cover freshness before that point and corrections after.
Rules that keep watermarks honest:
- Generate watermarks per source partition, not per task, so a slow partition holds back the watermark instead of producing late data.
- Mark a partition idle after
idle_partition_timeoutso an empty partition does not stall all windows; un-idle it on the next event. - Never let the watermark move backwards; on restore, start from the checkpointed watermark.
- Track watermark lag (processing time minus watermark) as the main freshness signal; it is the number a dashboard should show.
7.2 Deep dive: windows, triggers and late data
Windows decide where in event time results are computed; triggers decide when in processing time results are emitted; accumulation decides how successive results for the same window relate.
| Window type | Use | State cost |
|---|---|---|
| Tumbling (fixed) | Per-minute metrics | One open window per key plus lateness |
| Sliding (hopping) | Moving averages, for example 10 min every 1 min | One copy per overlapping window, or panes combined at firing |
| Session | User activity separated by a gap | Windows merge as events arrive; state per active session |
| Global with custom trigger | Count-based or per-key batching | Unbounded unless a trigger clears it |
| Accumulation mode | Each firing carries | Consumer must |
|---|---|---|
| Discarding | Only new data since last firing | Sum firings itself |
| Accumulating | Full value so far | Overwrite (upsert by window key) |
| Accumulating and retracting | New full value plus a retraction of the previous one | Apply retraction, then the new value (needed when results are regrouped downstream) |
Options for late data: drop silently; keep windows open forever; keep windows for an allowed lateness then send later events to a side output. Choice: allowed lateness of 10 minutes with accumulating firings and a side output. Reason: state cost is bounded (3.3), dashboards stay correct through ordinary device delays, and nothing is dropped silently: the side output feeds the daily reconciliation that compares stream totals with the batch recomputation (NFR-03).
7.3 Deep dive: keyed state and checkpoints
| Option | How it works | Strength | Weakness |
|---|---|---|---|
| A. Write every state change to an external database | State lives remotely | Simple recovery | One remote write per event; 2 million writes/s |
| B. Periodic stop-the-world snapshot | Pause all tasks, snapshot, resume | Simple consistency | Pauses the whole job; long at 25 GB |
| C. Aligned barrier snapshots | Coordinator injects numbered barriers at sources; an operator snapshots when barriers from all inputs arrived | Consistent without global pause; small checkpoints with incremental upload | Alignment waits under backpressure |
| D. Unaligned barrier snapshots | Barriers overtake buffered records; in-flight buffers are stored in the checkpoint | Checkpoint time independent of backpressure | Larger checkpoints; more restore work |
| E. Changelog per state update | Every update appended to a changelog log | Fast recovery with standby replicas | Doubles write traffic |
Choice: C by default, switching a checkpoint to D when alignment exceeds 60 s. Reason: aligned barriers give a consistent cut of all operator state and source offsets with no global pause and small checkpoints; the fallback keeps checkpoints completing under sustained backpressure, which is exactly when a recovery point matters most.
State snapshots are asynchronous: the task flushes its memtable, records the list of immutable files and continues processing while files upload. Files already uploaded by earlier checkpoints are referenced, not copied. Retain the last 3 completed checkpoints and delete unreferenced files with a reference count, never by age alone.
7.4 Deep dive: exactly-once state and output
Checkpoints make state exactly-once: after a failure, state and source offsets rewind together, so each event affects state once. Output is a separate problem because records emitted after the last checkpoint are emitted again on replay.
| Option | How it works | Fits | Cost |
|---|---|---|---|
| A. At-least-once output | Emit immediately; duplicates on replay | Metrics consumers that tolerate duplicates | Consumers deduplicate |
| B. Idempotent upsert | Output key is deterministic (campaign_id, country, window_start) and the value is a full accumulating result | Key-value and analytical stores | Needs accumulating mode and deterministic keys |
| C. Two-phase commit sink | Write into a transaction per checkpoint, pre-commit at the barrier, commit when the checkpoint completes | Transactional logs read with read-committed isolation | Output visible only after commit, so latency is at least the checkpoint interval |
| D. Write-ahead then publish | Buffer output in state, publish after checkpoint | Sinks without transactions | Duplicates possible if publish fails mid-way |
Choice: B for databases and C for the output log. Reason: B gives exactly-once effect with no extra latency because replays overwrite the same rows with the same values; C is the only way to give downstream stream consumers exactly-once records, and the 30 s interval fits the 60 s freshness target (NFR-02). Record the pre-committed transaction IDs in the checkpoint so a restarted sink can commit or abort them; set the transaction timeout well above the longest expected recovery, or a commit after recovery fails and data is lost.
7.5 Backpressure, hot keys and rescaling
- Backpressure: use credit-based flow control between tasks: a receiver grants buffer credits and a sender sends only with credit, so a slow sink slows its upstream tasks instead of growing unbounded queues. Expose the share of time each task is backpressured and the source lag.
- Hot keys: a campaign that gets 10% of all traffic overloads one task. Pre-aggregate before the shuffle (each source task combines events per key for a short interval), then merge partial results after it. For non-mergeable logic, salt the key and add a second merge stage.
- Rescaling: take a savepoint, restart with the new parallelism, assign key-group ranges to tasks and restore only those ranges. Source partitions are reassigned; the source offsets in the savepoint keep reads exact.
- Upgrades: give every stateful operator a stable ID; refuse an upgrade whose operator IDs or state schemas cannot be matched (error 409 in 4.4).
7.6 How real systems do it
How real systems do it (paraphrased, not copied). Akidau and colleagues at Google described the Dataflow model in "The Dataflow Model: A Practical Approach to Balancing Correctness, Latency, and Cost in Massive-Scale, Unbounded, Out-of-Order Data Processing" (PVLDB vol. 8 no. 12, 2015). They argue that pipelines should stop assuming data will ever be complete and should instead let authors choose explicitly among correctness, latency and cost. The model separates what is computed (transformations), where in event time (windowing, including merging session windows), when results are materialised (watermarks and triggers) and how later results relate to earlier ones (discarding, accumulating, or accumulating with retractions). Separately, Carbone and colleagues described lightweight asynchronous barrier snapshots for dataflows (arXiv 1506.08603, 2015), the basis of the aligned checkpoint approach in 7.3. Read both papers for the reasoning; this template only reuses the concepts.
8. Scalability and performance
| Concern | Approach | Limit before redesign |
|---|---|---|
| Ingest | Source parallelism equals partitions | Example: 128 partitions per topic; add partitions with a planned rescale |
| Shuffle | Pre-aggregation before keyed exchange | Network per worker |
| State growth | TTL on dedup and session state; LSM compaction tuning | Example: about 50 GB per task before restore time breaks NFR-04 |
| Checkpoint duration | Incremental, asynchronous, unaligned fallback | Upload bandwidth to object storage |
| Many small jobs | Shared session cluster for small jobs, dedicated cluster for large | Coordinator memory per job |
| Hot keys | Two-stage aggregation | One key above one task's capacity after combining |
Latency budget for an on-time result (NFR-02, Example):
| Step | Budget |
|---|---|
| Producer to log | 2 s |
| Watermark delay (bounded out-of-orderness) | 30 s |
| Processing and shuffle | 2 s |
| Commit wait for transactional sinks (half an interval on average, up to 30 s) | 15 s typical |
| Headroom | 11 s |
9. Reliability, security and operations
9.1 Failure-mode table
| Component | Failure | Detection | Blast radius | Mitigation | RTO |
|---|---|---|---|---|---|
| Worker | Process or host lost | Heartbeat timeout 10 s | Tasks of the jobs on that worker; whole job rewinds | Restart from last checkpoint; spare slots reserved | Example: under 3 min to fresh output |
| Job coordinator | Leader lost | Coordination-service lease expiry | Scheduling and checkpoints of one job | Standby takes leadership, reads latest pointer | Example: under 1 min |
| Object storage | Slow or unavailable | Checkpoint duration and failures | New checkpoints fail; processing continues | Tolerate N failed checkpoints, then alert; never delete the last good one | Depends on provider |
| Source partition | Stalled or idle | Per-partition watermark lag | Windows for all keys stall | Idle timeout; alert on stuck partition | Example: 60 s |
| Sink | Transaction commit fails after recovery | Commit error with expired transaction | Lost output for one interval | Transaction timeout well above recovery time; alert | Manual replay from savepoint |
| Late data surge | Device backlog arrives hours late | Side-output rate | Results for old windows | Reconciliation job; optional backfill job | Next reconciliation |
| Poison event | Deserialisation or logic error | Task restarts in a loop | Whole job | Dead-letter route for bad records; restart backoff | Example: 5 min |
| [Component] | [Failure] | [Signal] | [Scope] | [Mitigation] | [Time] |
9.2 Security
| Threat | Control |
|---|---|
| Job code runs with broad data access | Per-job service identity; source and sink permissions scoped per job |
| Sensitive fields in state and checkpoints | Encrypt object storage and local disks; drop or tokenise personal fields at the source operator |
| Tampered artifacts | Signed job artifacts verified at submission |
| Data retention in checkpoints | Checkpoint retention aligned with the data retention policy; savepoints catalogued and expired |
| [Threat] | [Control] |
9.3 Observability
| Signal | Metric | Alert threshold |
|---|---|---|
| Freshness | Watermark lag per job | Example: above 120 s for 5 min |
| Input health | Source lag in records and time | Growing for 10 min |
| Checkpoints | Duration, size, failures, alignment time | 3 consecutive failures |
| Backpressure | Share of time backpressured per task | Above 50% for 15 min |
| Late data | Side-output events/s | Above baseline x 5 |
| Correctness | Daily diff versus batch recomputation | Any window above 0.1% difference |
10. Trade-offs and alternatives
| Decision | Options | Chosen | Why | What we give up |
|---|---|---|---|---|
| Time domain | Processing time; event time | Event time with heuristic watermarks | Reproducible results under replay and delay | Watermark delay adds latency |
| Late data | Drop; keep forever; allowed lateness + side output | Allowed lateness + side output | Bounded state, nothing dropped silently | Corrections after the on-time result |
| State location | Remote database; embedded LSM; heap | Embedded LSM on SSD | Large state, incremental checkpoints | Local disk management |
| Checkpoint | Stop the world; aligned; unaligned; changelog | Aligned with unaligned fallback | Consistent cut, small checkpoints | Complexity of two modes |
| Output guarantee | At-least-once; idempotent upsert; two-phase commit | Upsert for stores, 2PC for logs | Exactly-once effect where needed | Commit latency for log readers |
| Engine | Build; adopt an open-source engine; managed service | [Choice] | [Reason] | [Cost] |
| At 10x load | 20 million events/s, 250 GB state | Partition sources further, raise parallelism within 1 024 key groups, add a standby-replica option to cut restore time | Restore of larger state dominates recovery | More hardware; checkpoint bandwidth becomes the bottleneck |
| At 0.1x load | 200 000 events/s, 2.5 GB state | Run on a shared session cluster with 8 tasks; heap state may suffice | Lower operating cost | Less isolation between jobs |
11. Delivery plan and risks
11.1 Milestones
| Milestone | Scope | Exit criterion | Target date |
|---|---|---|---|
| M1 | One job, event-time windows, upsert sink, shadow run next to the batch job | Daily diff below 0.1% for 14 days | YYYY-MM-DD |
| M2 | Checkpoints with failure drills | Kill-worker drill meets NFR-04 three times | YYYY-MM-DD |
| M3 | Transactional log sink; downstream consumers switch | Consumers read committed output only | YYYY-MM-DD |
| M4 | Rescaling and upgrades via savepoints | Rescale 64 to 128 at peak without data loss | YYYY-MM-DD |
11.2 Rollout and rollback
[Example: Run the stream job in parallel with the batch job for one month; dashboards switch per team behind a flag. Rollback restores the previous job version from its last savepoint and points dashboards back to batch results.]
11.3 Risks
| ID | Risk | Likelihood | Impact | Mitigation | Owner |
|---|---|---|---|---|---|
| R-01 | Example: Watermark bound too tight, many events late | Medium | Medium | Measure the lateness distribution; tune max_delay per source | [@name] |
| R-02 | Example: State grows without bound in session windows | Medium | High | Session gap maximum; state TTL; alert on state size | [@name] |
| R-03 | Example: Transaction timeouts lose output after long recovery | Low | High | Timeout above worst-case recovery; drill | [@name] |
| R-04 | Example: Teams misread early firings as final numbers | High | Medium | pane.timing in every record; dashboards label speculative values | [@name] |
| [R-nn] | [Risk] | [L / M / H] | [L / M / H] | [Mitigation] | [@name] |
12. Appendices
12.1 Open questions
| ID | Question | Owner | Due |
|---|---|---|---|
| OQ-01 | Example: Do finance reports read early firings or only final values? | [@name] | YYYY-MM-DD |
| OQ-02 | Example: Is a standby state replica worth the doubled write traffic? | [@name] | YYYY-MM-DD |
| [OQ-nn] | [Question] | [@name] | YYYY-MM-DD |
12.2 Glossary
| Term | Meaning |
|---|---|
| Event time | When the event happened, carried in the record |
| Processing time | When the engine processes the event |
| Watermark | The engine's estimate that no more events older than a timestamp will arrive |
| Trigger | Rule that decides when a window emits a result |
| Pane | One emission of a window; early, on-time or late |
| Allowed lateness | How long a window's state is kept after the watermark passes its end |
| Key group | The unit of keyed state that moves between tasks on rescale |
| Barrier | Marker injected into streams that separates records of two checkpoints |
| Savepoint | A user-triggered, retained checkpoint used for upgrades and rescaling |
| [Term] | [Meaning] |
12.3 Related templates
- Message Queue System Design (
system-design/design-message-queue): the partitioned logs this engine reads and writes. - CDC Pipeline System Design (
system-design/design-cdc-pipeline): database changes as an input stream. - Distributed Lock and Coordination Service System Design (
system-design/design-distributed-lock-coordination): coordinator leader election and checkpoint pointer. - Data Pipeline Specification (
ai-data/data-pipeline-spec): contracts, quality checks and ownership for each job. - Event Sourcing and CQRS (
architecture/event-sourcing-cqrs): read models fed by stream jobs.
12.4 References
| Reference | Use |
|---|---|
| Akidau T. et al., "The Dataflow Model: A Practical Approach to Balancing Correctness, Latency, and Cost in Massive-Scale, Unbounded, Out-of-Order Data Processing", PVLDB vol. 8 no. 12, 2015 | Windows, watermarks, triggers, accumulation (7.1, 7.2, 7.6) |
| Carbone P. et al., "Lightweight Asynchronous Snapshots for Distributed Dataflows", arXiv 1506.08603, 2015 | Barrier snapshots (7.3) |
| Kleppmann M., Riccomini C., Designing Data-Intensive Applications, 2nd ed., 2026 (inspiration only) | Stream processing background |
| RFC 9457 Problem Details for HTTP APIs | Error bodies (4.4) |
Standard and licence note
Based on the publicly described Dataflow model and asynchronous barrier snapshot technique cited in 12.4; no standard governs stream processing engines. This is a reference design to adapt, with illustrative numbers marked Example. Original text written for this collection; the cited papers and books were used as inspiration only and no text, figures or diagrams were copied. Check the current versions of the papers and of any engine you adopt. Template licence: MIT.
Templat terkait
Zanzibar-Style Authorization Service System Design Template
Relationship-based authorization service: relation tuples, namespace config, Check/Expand/List/Watch APIs, consistency tokens, caching, sharding, failure modes
Desain SistemCDC Pipeline System Design Template
CDC pipeline: log-based capture, watermark chunked snapshot, per-key order, schema evolution, outbox, search, cache and warehouse sinks, replay
Desain SistemChat System Design Template (Reference Design)
Real-time 1:1 and group chat: WebSocket gateways, per-conversation ordering, fan-out, receipts, offline sync, push, E2EE