Batch vs Streaming: Beginner
Batch: collect a pile, then process it
Streaming: process each record as it arrives
Watch the clock in the animation. At 07:40 the second signup, from Germany, lands in the queue. Within 2 seconds live_counts shows DE at 1, while daily_counts holds nothing, because its job will not run for another 18 hours. At 02:00 on April 25 the nightly job fires, reads all 6 signups, and 8 minutes later writes US 3, DE 2, IN 1 in a single overwrite. Both tables now hold identical numbers. They arrived on 2 different rhythms, and for most of the day only one of them was right.
What changes, in one table
| Dimension | Batch | Streaming |
|---|---|---|
| Trigger | A time on a schedule | A record arriving |
| Unit of work | A window of records, such as one day | 1 record |
| Compute lifetime | Starts at the trigger, exits when finished | Started once, runs for months |
| Output write | The whole result, replaced each run | 1 row updated per record |
| Freshness | As old as the time since the last run | Seconds |
| Cost | Minutes of compute per run | Every hour of every day |
- ▸The source: the same signups table feeds both pipelines.
- ▸The transform logic: count by country, in both cases.
- ▸The storage and the consumer: a table of counts, read by a dashboard.
- ▸What differs is when the transform runs, how much it handles per run, and how long it stays alive.
Freshness and lifetime
Two words from that table carry the rest of this lesson. Freshness is the delay between a record being created and its effect showing in the output. For s4, the signup from India at 15:30, that delay is 2 seconds in live_counts and 10 hours and 38 minutes in daily_counts. Compute lifetime is how long the transform exists as a running process. The batch job lives for 8 minutes a day. The stream consumer lives for all 1,440 minutes of it, including the roughly 1,434 in which no signup arrives. Freshness is what the consumer feels. Lifetime is what the bill feels.
Which of these 4 pipelines is batch?
The scheduler submits the job once a night. The job reads yesterday's signups, writes one table, and exits. Between runs the middle box has no running process.
One run, minute by minute
| Clock | What happens | Compute state |
|---|---|---|
| 02:00:00 | The scheduler reaches the trigger time and submits the job | Starting: a machine is requested |
| 02:01:00 | The job's process is up and connects to the signups database | Running |
| 02:01:30 | It reads every signup dated April 24 | Running: reading |
| 02:06:00 | It counts the rows per country in memory | Running: computing |
| 02:07:30 | It overwrites `daily_counts` with the new rows | Running: writing |
| 02:08:00 | The job reports success and its process exits | Shut down |
| 02:08 until 02:00 next day | Nothing runs. The scheduler watches the clock | Off |
The window is the boundary
The WHERE clause draws the window. The run at 02:00 on April 25 owns signups dated April 24 and nothing else. A signup at 23:59 on April 24 is counted 2 hours and 9 minutes after it happened. A signup at 00:01 on April 25 belongs to the next window and waits until 02:08 on April 26, which is 26 hours and 7 minutes. Two records created 2 minutes apart show up in the output 24 hours apart, and that gap is the price of a daily window.
Every run replaces its result
The animation wrote daily_counts in overwrite mode, and that is the usual batch choice. Each run produces the complete answer for its window and replaces whatever the previous run wrote for it. If the job fails at 02:05 and someone restarts it at 02:20, the second attempt reads the same April 24 rows, computes the same counts, and leaves the table exactly as a successful first attempt would have. A batch run is a unit you can repeat, because its window closed when the day ended.
A user signs up at 02:03 on April 25, while the nightly job is already running. When does that signup first appear in daily_counts?
A record moves from the app to the dashboard in about 2 seconds. The counter box never exits.
One event, source to sink
Follow signup s2, a user in Germany who presses the signup button at 07:40:00 on April 24.
| Clock | Where s2 is | What happens |
|---|---|---|
| 07:40:00.000 | Signup app | The app saves the user and publishes `{id: s2, country: DE}` to the queue |
| 07:40:00.040 | Queue | The queue appends the record after `s1` and offers it to consumers |
| 07:40:00.120 | Stream counter | The consumer, blocked waiting for input, receives `s2` |
| 07:40:00.125 | Stream counter | It reads the current DE count from the sink, 0, and computes 1 |
| 07:40:02.000 | `live_counts` | It writes the row DE, 1 and tells the queue that `s2` is done |
| 07:40:02.300 | Live dashboard | The next screen refresh reads DE, 1 |
Two seconds after someone in Germany pressed a button, a screen in the office shows the new count, and nothing was scheduled to make that happen. The consumer was waiting at 07:39, it processed s2 at 07:40, and it returned to waiting at 07:40:02 for s3, which arrives at 11:05. For 3 hours and 25 minutes the process is alive, allocated, billed, and doing nothing except waiting.
That for loop is the entire transform. queue.subscribe blocks until a record is available, so the loop body runs once per signup and never on a timer. live_counts.get fetches the current count for one country. upsert inserts that country's row or replaces it, 1 row rather than the whole table. mark_done tells the queue the consumer has finished s2, so a consumer that crashes and restarts resumes at s3 instead of rereading the day from s1.
The queue is the shock absorber
The queue sits between the app and the consumer so that neither waits for the other. The app publishes a record in 40 milliseconds and goes back to serving the user. If the consumer is taken down for an upgrade at 15:00, signup s4 at 15:30 lands in the queue and sits there. When the consumer returns at 15:45 it reads s4 and carries on. The queue turned a 45 minute outage into a 15 minute delay for 1 record, and the app never noticed. Without the queue, the app would have had to wait for the counter or drop the record.
- The next read is hours away, so nobody sees it
- A rerun reads the same closed window
- Same output, finished later
- New records wait in the queue
- Readers see a frozen, stale table
- Restart resumes at the first unfinished record
Signups feed both pipelines from the animation. At 15:00 on April 24 the stream consumer is stopped for an upgrade and restarted at 15:45. The nightly job runs as usual at 02:00 on April 25. At 02:10 on April 25, what does each table show for IN?
On a day with 6 signups, the consumer works for about 12 seconds and waits for the other 23 hours, 59 minutes and 48 seconds. The rhythm is streaming regardless of volume.
At 11:05 signup s3, from the US, lands in the queue. At 11:05:05 on April 24, what do the 2 tables show for US?
| Tier | Maximum age when read | Example request | What delivers it |
|---|---|---|---|
| Sub-second | Under 1 second | Block a card swipe that looks stolen before the terminal says approved | A stream consumer holding the data it needs in memory |
| Seconds | Between 1 and 60 seconds | A wall screen showing orders placed in the last minute | A streaming pipeline writing to a serving table |
| Minutes | Between 1 and 60 minutes | An on-call engineer checking whether signups dropped after a release | A batch job scheduled every 5 to 15 minutes |
| Hours or more | Between 1 hour and 1 day | The Monday morning review of last week's signups by country | A nightly or hourly batch job |
Three questions that produce a number
One request, three translations
| Who asks | What they do with it | Tier | Architecture |
|---|---|---|---|
| Head of marketing | Reviews signups by country at the Monday 10:00 meeting | Hours | Nightly batch, finished by 03:00 |
| On-call engineer | Wants to see a drop within 5 minutes of a release so a bad release can be rolled back | Minutes | Batch every 5 minutes over the last 5 minutes of signups |
| Growth team | Closes a promotion the moment the 1,000th signup lands, so nobody is promised a gift that is gone | Seconds | Stream consumer keeping a running count |
- ▸Replace 'real time' with 'no older than N seconds when read' and get the requester to agree to N.
- ▸Tie N to a decision: what is done differently if the number is 10 minutes old instead of 10 seconds?
- ▸Record N beside the pipeline. Whoever maintains it next year needs to know which tier it serves.
The finance team says daily revenue totals must be real-time. In conversation you learn they review the totals at 09:00 each morning and again at 17:00. Which tier and architecture fit?
Step 1: the tier narrows the field
| Consumer's tier | Choice | Why |
|---|---|---|
| Hours or more | Batch, nightly or hourly | One short run per window delivers the number before anyone reads it |
| Minutes | Batch on a short schedule | A job every 5 to 15 minutes meets the tier at a fraction of always-on cost |
| Seconds | Streaming | Only a consumer that is already running can react within seconds of each record |
| Sub-second | Streaming, with its data in memory | Even a write to a serving table may take too long at this tier |
Step 2: the cost you accept
- Write the consumer's freshness tier down before choosing a shape
- Default to batch, and make streaming earn its place with a seconds tier
- Price both shapes with the same hourly rate so the comparison is fair
- Feed a batch and a stream from one source when 2 consumers need 2 tiers
- Build streaming because the request contained the words real time
- Schedule a batch every 30 seconds to avoid admitting the case is streaming
- Judge cost by the bill alone and forget who restarts a crashed consumer at 03:00
- Let the loudest requester set the tier for every consumer of a table
Four cases, decided
| Use case | Who reads it, and when | Tier | Choice |
|---|---|---|---|
| Nightly sales report by region | Regional managers, at 08:00 | Hours | Batch at 02:00 over the previous day |
| Card swipe fraud score | The payment terminal, before it prints a receipt | Sub-second | Streaming, scoring each swipe as it arrives |
| Dashboard of failed logins | An on-call engineer, glancing every 10 minutes | Minutes | Batch every 10 minutes over the last 10 minutes |
| Monthly invoice generation | The billing system, on the 1st of each month | Hours or more | Batch on the 1st over the previous month |
A support team wants to see a customer's total order count when that customer calls. Calls arrive all day. The team says an order placed 2 hours ago is fine to miss. Which choice fits?
> A ride-hailing company such as Uber moves the same trip events down 2 paths. Surge pricing has to reflect each neighborhood's ride requests from the last 30 seconds, a seconds tier that only an always-on consumer counting requests as they arrive can serve. Each driver's weekly pay summary is produced once, after the week closes, which a single batch run over 7 days of completed trips serves comfortably. Both read the same trips. One consumer is a pricing engine reacting in seconds, the other is a driver opening a statement on Tuesday morning.
Two rhythms move data: wait and process the pile, or handle each record the moment it lands.
- Category
- Pipeline Architecture
- Difficulty
- beginner
- Duration
- 25 minutes
- Challenges
- 9 hands-on challenges
Topics covered: Two Ways Data Can Move, Batch: Picture, Rhythm, Example, Streaming: Picture, Rhythm, Example, What Real-Time Actually Means, Picking Batch or Streaming
Lesson Sections
- Two Ways Data Can Move (concepts: Batch vs Streaming)
The last lesson gave every pipeline 4 roles: a source, a transform, storage, and a consumer. Rhythm is a different question: when does the transform run, and how much data does it handle each time? Every pipeline answers in one of 2 ways, and the answer sets the cost, the freshness of the output, and the kind of failure you will be paged for. Batch: collect a pile, then process it A batch pipeline lets records accumulate and processes them together on a schedule. Signups land in an application d
- Batch: Picture, Rhythm, Example (concepts: Batch Processing)
A batch pipeline has 3 moving parts beyond the data itself: a scheduler that knows when to fire, a job that does the work, and the storage the job reads from and writes to. The scheduler is the only part awake all the time, and its whole task is to watch a clock. The job is where compute starts, runs, and shuts down, and that lifecycle is what this section traces, minute by minute. One run, minute by minute Three points on that timeline matter more than the rest. Compute starts at 02:00, when th
- Streaming: Picture, Rhythm, Example (concepts: Stream Processing)
A streaming pipeline also has 3 parts beyond the data: a queue that holds records in arrival order, a consumer process that reads them, and a sink that receives the results. The consumer plays the roles of both the scheduler and the job from the batch picture. It is started once and expected to stay up for months. There is no trigger time to look up, because the arrival of a record is the trigger. One event, source to sink The queue is the shock absorber On a day with 6 signups, the consumer wor
- What Real-Time Actually Means (concepts: Batch vs Streaming)
'Real-time' is a request, and requests arrive without numbers attached. When a product manager asks for signups in real time, the engineer's job is to turn those words into a freshness tier: the maximum age the number may have at the moment someone reads it. Four tiers cover almost every request, and each tier points to a different architecture and a different bill. Each tier is about 60 times stricter than the one below it, and the architecture changes with it. Hours and minutes are both served
- Picking Batch or Streaming (concepts: Batch vs Streaming)
The choice comes down to 2 inputs: the consumer's freshness tier, which the previous section taught you to extract, and how much the owner is willing to pay and to operate. Batch wins by default. Streaming wins when the tier demands it and the budget accepts it. This section puts numbers on both inputs so the decision stops being a matter of taste. Step 1: the tier narrows the field Step 1 settles the decision for most consumers, because most consumers read reports, and reports sit in the hours