ediverse Explore the platform

Spotlight PEPPOL BIS Billing 3.0 The EU e-invoicing mandate is here — France Sept 2026, Belgium Jan 2026, Germany 2025.

Sliding Window

How to obtain a continuously refreshed view of a metric over a recent time window, without waiting for a complete bucket to close.

Problem

Tumbling Window answers "how many in this hour?" with a single emission at the end of the hour. But for operational cases ("what is the error rate over the past 5 minutes?", "what is the average AS4 latency over the past 60 seconds?"), we need a continuously refreshed answer, not waiting 5 minutes for the next point. This requires a window whose end always advances but which always covers the same duration — a sliding window.

Forces

  • Storage cost: each event belongs to (size/step) windows simultaneously; proportional state multiplication.
  • Emission cost: one emission per step (every 10 seconds, for example) instead of one per size.
  • Visual granularity: the smaller the step, the smoother the curve, but the more the cost explodes.
  • Late data: same problem as tumbling, but worsened by the multiplication of open windows.
  • Approximation: for very large windows, sketches (HyperLogLog, Count-Min) are often used instead of an exact state.

Solution

Define a size W (duration covered by the window) and a step S (interval between two emissions). At time t, the active window covers [t-W, t]. If S < W (standard case), each event belongs to W/S windows. At each step S, the aggregate of events in the current window is emitted. Flink implementation: stream.window(SlidingEventTimeWindows.of(Time.minutes(5), Time.seconds(30))) computes a 5-minute window emitted every 30 seconds. For very large windows (hour, day) on very high-throughput streams, prefer an incremental sketch (HyperLogLog for distinct count, t-digest for percentiles) that maintains bounded state.

Structure

Time:     T-W ─────────────── T ─── T+S ─── T+2S ───►
              ◄─── Window 1 ──►
                    ◄─── Window 2 ──► (slid by S)
                          ◄─── Window 3 ──►

Event arriving at time t belongs to all windows W_i such that
  W_i.start ≤ t < W_i.end

Configuration "size 5min, slide 30s":
  Event at 10:00:15 belongs to windows ending at:
    10:00:30, 10:01:00, 10:01:30, ..., 10:05:00
  → 10 windows simultaneously

Emission cadence:
  Every 30 seconds, system emits aggregate over last 5 minutes.

EDI implementation

Three canonical EDI cases. (1) Real-time SLA: AS4 success rate over the past 5 minutes emitted every 30 seconds — feeds an SRE dashboard, triggers an alert if < 99.5 %. (2) Volume anomaly detection: if the number of invoices emitted over the past 10 minutes exceeds the historical mean for this time-of-day band by 3σ, alert (may signal a partner recovering from outage and replaying its backlog). (3) Operational trending: top-5 most frequent SBDH error codes over the past 15 minutes — emitted every minute to identify a degradation quickly. Spark implementation: df.groupBy(window(col("eventTime"), "5 minutes", "30 seconds"), col("partner")).count(). Mind allowed lateness and state TTL; without them, memory consumption explodes within a few hours.

Anti-patterns

  • Step too fine (1 second on 1h window) — 3 600 simultaneous windows per key, unmanageable state.
  • Sliding on very-high-cardinality data (by message ID) — explodes state immediately.
  • No TTL state — RocksDB grows unbounded until OOM.
  • Emitting on every event instead of every step — operator emits too many downstream events.
  • Confusing sliding and hopping windows — Beam and Flink terminology diverges slightly; read the docs.

Sources