Batch vs streaming: how to choose
Batch processing handles a bounded set of data in one run, then stops; streaming processes events continuously as they arrive, on data that has no end. The decision rule for exams: choose by the latency the business asks for, not by what sounds modern. If a result is needed once an hour or once a day, batch is simpler and cheaper; if the stem says “as events arrive”, “within seconds” or “near real time”, use a streaming engine; if it says “incrementally, but only run when scheduled”, the middle option (a streaming engine run in batch-like mode) is often the answer.
The choice in one table
| Question | Batch | Micro-batch / Structured Streaming | Event-at-a-time streaming |
|---|---|---|---|
| Input | Bounded dataset (a day of files, a table snapshot) | Unbounded stream, read in small increments | Unbounded stream, one event at a time |
| Typical latency | Minutes to hours | Seconds | Sub-second |
| Result is | Complete after each run | Updated after each trigger | Updated per event |
| Failure handling | Re-run the job | Restart from a checkpoint | Engine-specific |
| Complexity and cost | Lowest | Moderate | Highest |
| Examples | Nightly load into a warehouse, pipeline Copy activity | Spark Structured Streaming into Delta | Dedicated stream processors, Spark’s experimental continuous processing mode |
Micro-batch is the idea that makes Spark Structured Streaming work: the engine treats the stream as an ever-growing input table and processes new rows in small batches. Apache Spark’s documentation describes it this way: at each trigger, new rows are appended to the input table and the result table is updated, and the engine “reads the latest available data from the streaming data source, processes it incrementally to update the result, and then discards the source data.” The API deliberately matches batch: you use spark.readStream and writeStream with the same DataFrame operations. That is why one codebase can serve both modes, a point that features in lakehouse and medallion designs (see medallion architecture).
What a trigger decides
In Structured Streaming the trigger controls when a micro-batch runs. With no trigger set, the engine starts the next batch as soon as the previous one finishes. A fixed interval, such as trigger(processingTime="1 minute"), runs on a schedule. trigger(availableNow=True) processes everything available at start, in as many batches as needed, and then stops. That last option is the common exam answer for “ingest new files incrementally, but run it as a nightly job to save cost”: it keeps the streaming bookkeeping (checkpoints, exactly-once) while behaving like a batch job.
Worked example: counting orders per 10 minutes
A shop sends order events with a timestamp set by the app. A dashboard needs the number of orders per 10-minute window.
counts = (events
.withWatermark("order_time", "15 minutes")
.groupBy(window("order_time", "10 minutes"))
.count())
Three ideas are in those lines.
- Event time versus processing time.
order_timeis when the event happened; processing time is when the engine sees it. Mobile devices and queues deliver late, so aggregating by event time gives the correct answer and aggregating by arrival time does not. - Windows. Spark’s
window(col, "10 minutes")is a tumbling window: fixed size, no overlap, each event in one window. Adding a slide,window(col, "10 minutes", "5 minutes"), gives overlapping (hopping or sliding) windows, andsession_windowgroups events until a gap of inactivity. Fabric eventstreams, which share their windowing functions with Azure Stream Analytics, offer tumbling, hopping, sliding, session and snapshot windows. - Watermark. The engine cannot keep state for every window forever. The watermark is the largest event time seen minus the delay (15 minutes here). Per the Spark documentation, data delayed by less than the threshold is never dropped, data delayed by more may or may not be processed, and a window’s state is cleaned up once the watermark passes its end. In Append output mode a window’s final count is emitted only after the watermark passes the window end, so results appear late but never change. Update mode emits revised counts as they arrive.
The trade-off to remember: a longer watermark tolerates later data and costs more state and delay; a shorter one is cheaper and drops more late events.
Checkpoints and delivery guarantees
A streaming query needs a checkpointLocation. The engine records the offset range processed in each trigger, so a restarted query resumes where it stopped instead of reprocessing hours of data. Spark states that with replayable sources and idempotent sinks, Structured Streaming can provide end-to-end exactly-once semantics; the file sink is exactly-once, while Kafka and foreachBatch sinks are at-least-once by default, so foreachBatch needs the batch id for deduplication. On Delta tables this combines with the transaction log; see Delta Lake explained.
Eventstreams in Fabric
An eventstream in Microsoft Fabric Real-Time Intelligence is a no-code way to capture events, transform them and route them. Microsoft Learn lists sources such as Azure Event Hubs, IoT Hub, Kafka, Amazon Kinesis, change-data-capture connectors and custom endpoints; no-code transformations including filter, manage fields, aggregate, group by (time windows), union, expand and join; and destinations including Eventhouse (query with KQL, see the KQL cheat sheet), Lakehouse (events converted to Delta tables), derived streams, Activator and custom endpoints. Some items are in preview, among them the SQL operator, the Spark Notebook destination and schema-aware eventstreams. The documentation lists at-least-once event delivery, a 1 MB maximum message size and up to 90 days of event retention.
Which exams test this
| Exam | How it appears | On this site |
|---|---|---|
| DP-700 | Ingest and transform data (30–35%): design full, incremental and streaming loading patterns, pick a streaming engine, process streams with Eventstream, Spark Structured Streaming or KQL, write windowing functions, handle late-arriving data | Ingest and transform |
| DP-750 | Prepare and process data (30–35%): choose batch or streaming as the loading method, ingest with Spark Structured Streaming, Lakeflow Connect or notebooks, and read streaming data from Azure Event Hubs | Prepare and process data |
| Databricks Spark Developer Associate | Structured Streaming (10%): the micro-batch model, exactly-once and fault tolerance, output modes and sinks, windowed aggregation, deduplication with and without a watermark | SQL, tuning, streaming |
| Databricks Data Engineer Associate | Data Ingestion and Loading (21%): batch, streaming and incremental ingestion patterns, Auto Loader and COPY INTO | Ingestion and platform |
| Databricks Data Engineer Professional | Outline from October 9, 2026, Developing Code for Data Processing (23%): stateful Structured Streaming (watermarks, output modes, foreachBatch, checkpoints), and choosing a streaming table or a materialized view for a latency and cost requirement | Databricks DE Professional: developing code |
| Databricks ML Associate | Minor topic, Model Deployment (12%): batch, real-time and streaming serving compared | Workflows and deployment |
| Databricks ML Professional | Minor topic: scoring a Spark ML model for a batch or streaming use case, and processing streaming data into real-time features | Model deployment |
| MLA-C02 | Minor topic, Data Preparation for ML and AI (28%): ingest from streaming sources such as Kinesis or Kafka and transform streaming data | Data preparation |
How exam questions are built around this choice
- Latency words decide. “Nightly”, “daily report” is batch. “Within seconds”, “as it happens” is streaming. “Alert when a threshold is crossed” suggests Eventstream with Activator.
- No-code or code? Light filtering and routing with no code is an Eventstream; complex PySpark logic with Delta output is Spark Structured Streaming; time-series querying is an Eventhouse.
- Late data. “Events arrive out of order or late” means event time plus a watermark.
- Restart without reprocessing. A checkpoint.
- Full or incremental load. Incremental loads, often with a stored high-water mark, are batch even though they are not full loads.
- Cost. Streaming keeps compute running;
availableNowor a scheduled batch is cheaper when freshness is not required.
Practice questions
Question 1. A data engineer ingests new JSON files from a landing folder into a Delta table using Structured Streaming. Freshness of one day is acceptable, and the team wants to avoid paying for a cluster that runs around the clock, while keeping checkpoint-based incremental processing. What should they configure?
- A. Leave the trigger unset so the query runs continuously
- B. Use a one-second processing-time trigger
- C. Use the availableNow trigger in a scheduled job
- D. Replace the stream with a full reload of the table every night
Show answer
Answer: C
The availableNow trigger processes all data available when the query starts, in as many batches as needed, and then stops, so a scheduled job keeps the incremental and checkpointed behaviour without a continuously running cluster. A default trigger keeps the query running and polling for new data. A continuous long-running query with a shorter interval costs more and is not needed for daily freshness. Rewriting the load as a full reload gives up incremental processing.
Question 2. A streaming aggregation counts events per 10-minute window using the event timestamp. Some events arrive up to 15 minutes late, and state for old windows must not grow without limit. Which approach meets both requirements?
- A. Group by the time the event arrived at the engine
- B. Use Complete output mode and keep all windows
- C. Disable checkpointing so that old state is discarded
- D. Apply a watermark of 15 minutes on the event-time column before the windowed aggregation
Show answer
Answer: D
A watermark on the event-time column with a 15-minute delay lets the engine accept events up to that late and drop state for windows older than the watermark. Grouping by arrival time gives wrong counts for late events. Complete output mode keeps the whole result table and does not bound state. Disabling checkpointing does not bound state either and removes restart safety.
Go deeper
- Structured Streaming: DataFrames, windows, watermarks (Apache Spark)
- Structured Streaming getting started: processing model and fault tolerance (Apache Spark)
- Microsoft Fabric Eventstreams overview (Microsoft Learn)
- Related on this site: Spark basics, DP-700 study plan, how to study for certification exams