beginner

Why Windowing?

5 min readLast updated: 2026-07-01

1. Introduction

In standard batch processing, datasets have a clear beginning and end. You can easily calculate the sum, average, or count of all elements because you have the entire dataset available. In streaming, however, data is unbounded—it flows continuously, with no starting or ending boundaries.

Windowing is the mechanism of partitioning an infinite, unbounded data stream into finite, manageable chunks (windows) based on temporal boundaries or other criteria. This allows us to perform meaningful aggregations over specific segments of time.

2. Why This Concept Exists

Without windowing, performing aggregations on a streaming data feed is practically impossible. If you write a pipeline that tries to compute the total number of transactions in an infinite stream, the system will attempt to accumulate elements forever. It will never emit a final result because the stream never ends, eventually causing the system to run out of memory.

Windowing solves this fundamental streaming problem by:

  • Dividing the infinite stream into finite segments (e.g., every 5 minutes, 1 hour, or 24 hours).
  • Enabling temporal aggregations like "What is the average CPU utilization of our servers over the last 10 minutes?" or "How many items did we sell in the last hour?"
  • Providing deterministic windows for analyzing real-world user behavior and system performance.

3. Key Terminology

  • Unbounded Data: An infinite dataset that grows continuously over time (e.g., IoT sensor readings, network traffic, user clickstreams).
  • Bounded Data: A finite dataset of a fixed size, typical of traditional databases or file storage.
  • Window: A temporal slice of a stream that holds a subset of elements (e.g., from 12:00:00 to 12:05:00).
  • Aggregation: A mathematical operation that reduces multiple values into a single value, such as a sum, average, or count.

4. How It Works

  1. Ingestion: Unbounded elements flow into the pipeline from a streaming source (such as Google Cloud Pub/Sub or Apache Kafka).
  2. Assignment: As each element passes through a windowing transform, the runner determines which window(s) the element belongs to, based on its timestamp.
  3. Grouping: Elements belonging to the same window are grouped together.
  4. Evaluation (Triggering): The pipeline runner monitors watermark progress. Once the watermark passes the end of a window, the runner triggers the aggregation.
  5. Emission: The accumulated result (e.g., the sum or count of the window's elements) is materialized and written to a downstream sink (such as BigQuery or Cloud Storage).

5. Visual Diagram

Window 1 (12:00 - 12:05)
Contains elements [e1, e2, e3]
Window 2 (12:05 - 12:10)
Contains elements [e4, e5, e6]
Window 3 (12:10 - 12:15)
Contains elements [e7...]

6. Code Example

The following pipeline reads an unbounded stream of user events, segments them into 5-minute fixed windows, and counts the events per window:

python
import apache_beam as beam
from apache_beam.transforms.window import FixedWindows

with beam.Pipeline() as p:
    (p
     | "ReadEvents" >> beam.io.ReadFromPubSub(subscription="projects/my-project/subs/events")
     | "ParseJson" >> beam.Map(lambda x: x.decode('utf-8'))
     | "ApplyWindowing" >> beam.WindowInto(FixedWindows(5 * 60)) # 5 minutes in seconds
     | "CountPerWindow" >> beam.CombineGlobally(beam.combiners.CountCombineFn()).without_defaults()
     | "LogResults" >> beam.Map(print))

7. Code Explanation

  • beam.io.ReadFromPubSub(...) reads messages from a Pub/Sub topic. This creates an unbounded PCollection.
  • beam.WindowInto(FixedWindows(5 * 60)) assigns each element to a 5-minute (300 seconds) window based on the element's event timestamp.
  • beam.CombineGlobally(beam.combiners.CountCombineFn()).without_defaults() aggregates and counts all elements inside each window.
  • without_defaults() is critical in streaming because it ensures that empty windows (windows with zero elements) do not emit default outputs (like 0), which would create infinite streams of zeros.

8. Real Production Example

In a financial fraud detection system, transaction logs are constantly streamed into a data pipeline. To detect rapid-fire credit card theft, the system must compute the number of transactions per card in a short window. The pipeline windows transaction events into 1-minute fixed windows. If a single credit card shows more than 5 transactions in any 1-minute window, the pipeline triggers an immediate security alert.

9. Common Mistakes

  • Omitting Windowing on Streaming Aggregations: Trying to perform a GroupByKey or Combine on an unbounded collection without applying a windowing strategy. This will cause the pipeline to stall or run out of memory.
  • Not using .without_defaults(): When using global combines (like summing or counting) on windowed collections, forgetting without_defaults() will lead to the runner attempting to produce empty values for every window, which is highly inefficient and often buggy in streaming pipelines.
  • Assuming Global Windows act as Streaming Windows: Assigning elements to the GlobalWindow (default) and expecting timed aggregations to occur. Elements in a global window are never finalized in streaming unless custom triggers are defined.

10. Interview Perspective

  • Question: Why does a GroupByKey or Combine require windowing on an unbounded PCollection?
  • Answer: Because an unbounded collection is infinite. Without windowing, the runner would have to wait forever for all elements to arrive before it could group them. Windowing bounds the keys within a finite time box, making the grouping possible.
  • Question: Can you apply windowing to batch datasets?
  • Answer: Yes. Even though batch datasets are bounded, windowing can group records by their embedded timestamps (e.g., analyzing historical logs grouped by hour of occurrence).

11. Best Practices

  • Always define the window size based on your business SLA (Service Level Agreement). If alerts must happen within minutes, use small windows.
  • Avoid excessively small window sizes (e.g., 1 second) unless necessary, as they increase metadata overhead and storage requirements.
  • Verify that your data source provides valid event timestamps; otherwise, Beam defaults to ingestion time, which may not match actual event time.

12. Summary

  • Windowing partitions infinite data streams into finite, temporal segments.
  • It is mandatory for grouping and aggregating unbounded PCollections.
  • Beam uses WindowInto to assign elements to windows.
  • Aggregations are computed independently within each window.
  • Use without_defaults() to avoid emitting empty placeholders for inactive windows.

13. Interactive Challenges

Challenge 1: Defining 10-Minute Windows (Beginner)

Fill in the missing transform to window a stream of data into 10-minute fixed windows.

Challenge 2: Ingestion-based Event Counter (Intermediate)

Write a complete pipeline structure within a context block that reads from a Pub/Sub topic subscription "projects/test/subs/inputs", windows the stream into 15-minute intervals, counts the total messages per window, and prints the result.

Challenge 3: Prevent Default Window Emitting (Advanced)

When aggregating a windowed stream, how do you prevent empty windows from emitting default values? Write a Python line showing how to apply a global sum to a windowed collection while preventing default emissions.

14. Related Content

Advertisement
AdSense Slot #000001Leaderboard Banner (728x90)