Batch vs streaming: how to choose

Updated October 9, 2026

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

QuestionBatchMicro-batch / Structured StreamingEvent-at-a-time streaming
InputBounded dataset (a day of files, a table snapshot)Unbounded stream, read in small incrementsUnbounded stream, one event at a time
Typical latencyMinutes to hoursSecondsSub-second
Result isComplete after each runUpdated after each triggerUpdated per event
Failure handlingRe-run the jobRestart from a checkpointEngine-specific
Complexity and costLowestModerateHighest
ExamplesNightly load into a warehouse, pipeline Copy activitySpark Structured Streaming into DeltaDedicated 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.

  1. Event time versus processing time. order_time is 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.
  2. 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, and session_window groups 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.
  3. 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

ExamHow it appearsOn this site
DP-700Ingest 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 dataIngest and transform
DP-750Prepare 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 HubsPrepare and process data
Databricks Spark Developer AssociateStructured Streaming (10%): the micro-batch model, exactly-once and fault tolerance, output modes and sinks, windowed aggregation, deduplication with and without a watermarkSQL, tuning, streaming
Databricks Data Engineer AssociateData Ingestion and Loading (21%): batch, streaming and incremental ingestion patterns, Auto Loader and COPY INTOIngestion and platform
Databricks Data Engineer ProfessionalOutline 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 requirementDatabricks DE Professional: developing code
Databricks ML AssociateMinor topic, Model Deployment (12%): batch, real-time and streaming serving comparedWorkflows and deployment
Databricks ML ProfessionalMinor topic: scoring a Spark ML model for a batch or streaming use case, and processing streaming data into real-time featuresModel deployment
MLA-C02Minor topic, Data Preparation for ML and AI (28%): ingest from streaming sources such as Kinesis or Kafka and transform streaming dataData 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; availableNow or 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