Based on the DEA-C01 exam guideReport an error
Even with the same data, the system design changes completely depending on "when, and how much at a time" you process it. Gathering a day's worth of orders every night to build a settlement report, and catching a fraudulent transaction the instant a payment happens, handle the same payment data but need entirely different machinery. The former is batch, the latter is streaming.
Today we look at the essence of these two processing paradigms, the cases each one suits, and the key trade-off that separates them: latency and throughput. The very first judgment a data engineer makes when designing a new pipeline is "is this batch or a stream?"
The difference is whether you process data in bundles or as it arrives.
Batch
[····· collect ·····] → process all at once → result
Bounded data, run on a fixed schedule
Streaming
→ arrive → process → arrive → process → arrive → process →
Unbounded data, flows without end
Batch deals with a finite bundle: "what piled up over the last hour/day." It has a clear start and end. Streaming deals with an infinite flow: "events that keep coming from now on, forever." Because it never ends, to produce a result you have to cut the flow into time windows such as "the last 5 minutes."
| Aspect | Batch | Streaming |
|---|---|---|
| Data | Bounded | Unbounded |
| Execution | Periodic (hourly/daily) | Continuous (always on) |
| Latency | Minutes to hours | Milliseconds to seconds |
| Throughput | Very high | Per-record processing |
| AWS examples | Glue, EMR, Batch | Kinesis, MSK, Flink |
💡 Related theory: The most important concept in streaming is windowing. To produce an aggregate from an infinite flow, you have to cut the flow into time units. The typical types are the tumbling window (fixed, non-overlapping intervals), the sliding window (overlapping and moving), and the session window (separated by gaps in activity). In addition, dealing with the difference between "the time the event occurred (event time)" and "the time the system received it (processing time)" is the central hard problem of streaming design.
There is only one criterion for choosing: how fresh does the result need to be?
Cases where batch fits:
Cases where streaming fits:
# Batch: collect a day of logs and aggregate once (Glue/Spark)
df = spark.read.parquet("s3://logs/date=2026-06-25/") # the whole day
daily = df.groupBy("region").agg(sum("amount"))
daily.write.parquet("s3://reports/daily/2026-06-25/")
# Streaming: aggregate flowing events in 5-minute windows (Flink/KDA)
events.window(TumblingWindow.of(minutes=5)) \
.key_by("region") \
.aggregate(SumAggregator()) # emits a result every 5 minutes, endlesslyThe key point is that "real time is expensive." Streaming demands always-on infrastructure and more complex operations. That is why asking "do we truly need real time, or is 5 minutes late okay?" is the starting point of cost optimization. If you vaguely go with "fresh data is good, so stream everything," cost and complexity explode.
Micro-batch is the midpoint between the two. Like Spark Structured Streaming, it repeatedly runs small batches at a very short interval (a few seconds) to produce "near real time." It achieves second-level latency while being simpler to operate than true event-by-event streaming, so many real-world pipelines choose this compromise.
These are the two metrics that quantitatively separate batch from streaming.
Batch : latency high ↑ throughput very high ↑↑↑
Stream : latency low ↓ per-record processing → cumulative throughput is lower
Because batch collects data and processes it all at once, the per-record overhead is amortized, so throughput is overwhelmingly high. In exchange, latency arises equal to the time spent collecting. Because streaming processes events the moment they arrive, latency is very low, but each record incurs processing and delivery cost, so the cumulative throughput the same infrastructure can deliver is lower than batch.
On top of this comes the axis of correctness. Streaming has to deal with late-arriving data and out-of-order events, so it must compromise between an "exact final result" and a "fast approximate result." Batch processes after all the data has arrived, so it is free of this problem.
correctness ↑
│
batch ● │
│ ● micro-batch
│
│ ● streaming
└──────────────────→ freshness (low latency) ↑
The classic solution to this trade-off at the architecture level is the Lambda Architecture. It runs a batch layer (accurate but slow) and a speed layer (fast but approximate) at the same time and merges them in a serving layer. Because of the burden of maintaining two copies of the code, the Kappa Architecture, which handles even batch with a single streaming engine, emerged as an alternative. On AWS, the Kinesis/MSK + Flink combination corresponds to Kappa.
This is the baseline that decides "which service to use for this scenario" on the exam.
| Paradigm | Ingestion | Processing | Representative scenario |
|---|---|---|---|
| Batch | S3 landing, DataSync | Glue, EMR, AWS Batch | Daily reports, large-scale ETL |
| Streaming | Kinesis Data Streams, MSK | KDA (Flink), Lambda | Real-time detection, live dashboards |
| Near-real-time | Kinesis Data Firehose | Firehose transformation, Lambda | Loading logs into S3/Redshift almost instantly |
You especially need to distinguish two easily confused services. Kinesis Data Streams is for true streaming that needs low latency and multiple consumers, while Kinesis Data Firehose is a "managed near-real-time delivery person" that takes a stream and automatically loads it into S3, Redshift, and so on. If you want the data dropped at a destination without operating consumers in your own code, it is Firehose.
"Real time" means different things to different people. Exam passages also distinguish between real-time, near real-time, within minutes, and daily. Splitting the latency requirement into ranges narrows the candidates.
| Required freshness | Processing form | AWS configuration | Behavior behind the rationale |
|---|---|---|---|
| Reaction within 1 second | Event-by-event streaming | KDS/MSK + Managed Service for Apache Flink, or Lambda (enhanced fan-out) | Enhanced fan-out receives records by push, with an average propagation delay of about 70 ms; shared throughput averages about 200 ms with a single consumer |
| A few seconds to 1–2 minutes | Near-real-time loading | Data Firehose | Delivers all at once when the buffer (size or time) fills. For an S3 destination the buffer interval is 0–900 seconds, 300 seconds by default |
| 1 to several minutes | Micro-batch | Glue streaming ETL | Based on Spark Structured Streaming. Reads and writes with a default 100-second window |
| Several minutes to hours | Event-driven batch | S3 event → Lambda/Glue job, EventBridge schedule | Runs a small batch when a file arrives or at a fixed interval |
| Daily | Scheduled batch | Glue, EMR, AWS Batch + Step Functions/MWAA | Reads a whole day's partition at once and aggregates in a single pass |
⚠️ Pitfall: Even if the passage says "load into S3 in real time," if the requirement is only "to accumulate," the answer is Firehose. KDS requires you to operate the consumer code yourself, so it conflicts with a "least operational overhead" condition. Conversely, when you see "multiple applications each read the same events" or "reprocess a past interval," Firehose alone will not do.
Unpacking "real time is expensive" through the pricing structure looks like this.
| Aspect | Batch | Streaming |
|---|---|---|
| When billing happens | Only while the job runs | The whole time the stream or application is up, even with no data |
| Ingestion layer | S3 storage and request charges | KDS provisioned mode is billed per shard; on-demand mode is billed by the data volume (GB) written and read |
| Processing layer | Glue by job run time, EMR by the time the cluster is on | A Glue streaming job is billed continuously for as long as it runs, and a Flink application also runs constantly |
| Operations | If it fails, rerun just that date | Constant need for lag monitoring, checkpoints, and preparation for duplicate processing on restart |
| Correctness | Compute after all data has gathered | You must decide how long to wait for late data |
This is a hard problem that exists only in streaming, not in batch.
ApproximateArrivalTimestamp is this. It is the stream arrival time, not the time the event occurred.5-minute tumbling window by event time [10:00~10:05)
10:01 event A ─ arrives 10:01 → aggregated normally
10:03 event B ─ arrives 10:04 → aggregated normally
10:02 event C ─ arrives 10:21 → what if the window has already closed? (late data)
YYYY/MM/dd/HH, UTC) is based on the time the record arrived at Firehose. To split folders by event time, you have to pull a field out of the record with dynamic partitioning.Batch reprocessing is safe thanks to its idempotent structure of "the same input partition → overwrite the same output partition." Streaming re-reads from the checkpoint after a failure, so some records can be processed twice (at-least-once), and you must design the results store to absorb the duplicates.
When the click times for the same user are 10:00, 10:02, 10:03, 10:11, 10:12, counting the events gives different results like this.
| Window | Definition | Result | Used for |
|---|---|---|---|
| Tumbling 5 min | Fixed, non-overlapping intervals | [10:00~10:05) 3 events, [10:10~10:15) 2 events | Sales total every 5 minutes, per-minute metrics |
| Sliding 10 min / 5-min step | A 10-minute window moves every 5 minutes, overlapping each other | [10:00~10:10) 3 events, [10:05~10:15) 2 events; one event can fall in multiple windows | "Moving average over the last 10 minutes," detecting anomalous spikes |
| Session (5-min gap) | The session ends if activity stops for more than 5 minutes | Session 1 10:00~10:03 3 events, session 2 10:11~10:12 2 events | Visit session length, grouping user behavior |
This is the next fork once you have settled on "process it with streaming."
| Criterion | Lambda | Managed Service for Apache Flink | Glue streaming ETL |
|---|---|---|---|
| Processing model | Function invocation per batch, stateless by default | Per-event, with built-in state and checkpoints | Micro-batch (Spark Structured Streaming) |
| Good at | Per-record cleansing, filtering, routing, notifications | Window aggregation, stream joins, event time and late-data handling | Receiving a stream, transforming it, and loading it into an S3 data lake or JDBC |
| Source | Event source mapping for KDS, MSK, DynamoDB Streams, etc. | KDS, MSK, etc. | KDS, Kafka, MSK |
| Operations | Lightest | You must pay attention to application parallelism and state size | Operated the same way as a Glue job, tracking read position with checkpoints (job bookmarks not supported) |
| Clue for choosing | "Simple transformation," "run a function per event" | "Stateful," "time window," "accurate aggregation" | "Reuse existing Spark/Glue code," "minute-level is enough" |
KDA (Flink) in the table above also refers to the same service.| Clue in the passage | Direction to choose | Reason |
|---|---|---|
| "Every night," "daily report," "the previous day's data" | Scheduled batch (Glue/EMR) | Bounded data, latency tolerated |
| "Recompute several years of historical data" | Batch (backfill) | Throughput matters, and the stream has no history |
| "Detect immediately when a transaction occurs," "alert within seconds" | KDS/MSK + Flink or Lambda | Event-level low latency |
| "Moving aggregate over the last N minutes," "session" | Managed Service for Apache Flink | Stateful window operations |
| "Keep loading into S3/Redshift without code" | Data Firehose | Managed near-real-time delivery |
| "Reuse an existing Spark job for the stream too, 1–2 minutes of delay acceptable" | Glue streaming ETL | Micro-batch |
| "Both real-time results and accurate final results" | Lambda Architecture (speed + batch layer) | The batch later corrects the approximate results |
| "Maintain only one copy of the pipeline code" | Kappa Architecture (reprocess by replaying the stream) | Removes the batch layer |
In the next post, we will spread out the full map of AWS data services that actually implement these processing paradigms, across the categories of ingestion, storage, processing, analytics, and governance.
Click a choice to reveal the answer and explanation.
Question 1
In streaming processing that deals with an unbounded data flow, which concept is indispensable for producing aggregation results from an infinite flow?
Question 2
Which processing paradigm is best suited for "collecting a full day's transactions every night to generate a settlement report," and why?
Question 3
What is the fundamental reason batch processing achieves higher throughput per unit of time than streaming?
Question 4
Which AWS service is best suited when you want stream data automatically loaded into S3 or Redshift almost immediately, without operating separate consumer code?
Question 5
Which classic architecture resolves the latency-correctness trade-off by operating a batch layer (accurate but slow) together with a speed layer (fast but approximate)?