Basis Lab

Answers · Where the data lives

Should I use a sliding window or a fixed window?

In shortUse a fixed window when the question names a period that must add up, and a sliding one when it asks about the recent past as of now. Questions about episodes want neither.

Use a fixed window when the question names a period that has to tile, and a sliding one when the question is about the recent past as of now. If the question is about an episode whose length belongs to the behaviour rather than to the clock, you want neither of them.

The question picks the shape

Per hour, per day, per calendar month: fixed. The giveaway is that somebody else named the period, usually for reporting or billing, and the parts have to add up to the whole. Adjacent fixed windows do not overlap and leave no gaps, so each event lands in exactly one of them and the monthly figure equals the sum of the daily ones. In the last five minutes, right now, this minute: sliding. The question is about a quantity that should be current, and no named period appears in it anywhere.

Alerting is the case that separates them. An error-rate alert run against an hourly fixed window reads whatever the last completed hour contained. Evaluated at an arbitrary moment, the oldest event behind that number is somewhere between zero and sixty minutes old, thirty on average, and the count drops back to zero at the top of each hour for a reason unconnected to the traffic. A five-minute window advancing every minute reports data no older than five minutes and never resets.

Under a sliding scheme an event is not a member of one window. With width ww and advance hh, a new window opens every hh minutes and each stays open for ww, so the event is still inside the ones that opened after it arrived until ww has elapsed. That is the count of windows it belongs to:

n=whn = \frac{w}{h}

A fifteen-minute window advancing every five minutes puts every event in 155=3\frac{15}{5} = 3 windows. A one-hour window advancing every minute puts every event in 601=60\frac{60}{1} = 60 of them, and each of those sixty has to be updated when the event arrives.

What the window costs to hold

Memory is the number of distinct keys times the number of windows open at once times the bytes in one accumulator. A fixed window holds one accumulator per key, for the window currently open, because earlier ones have been emitted and released. A sliding window holds one per open window, and the number open is the ratio just computed:

FIG 1State held by a sliding window
total memory held by the window state
distinct keys with activity in the window
window width
the advance, how often a new window opens
bytes in one accumulator
The middle term is the whole story, and it is not a tuning constant. People choose the advance for how smooth they want the output to look, then discover they have chosen a memory multiplier.

At two hundred bytes an accumulator, twelve regions on a one-hour window advancing every minute hold 12×60×200=144,00012 \times 60 \times 200 = 144{,}000 bytes, which is 144 kilobytes and not worth a meeting. Change only the key and the same window definition becomes a capacity problem.

FIG 2
keyed ondistinct keysaccumulators (keys x 60)state at 200 bytes
region12720144 kilobytes
customer account50,0003,000,000600 megabytes
user identifier4,000,000240,000,00048 gigabytes

The window is identical in every row. Only the number of distinct keys changed, and the state moved by five orders of magnitude.

The common mistake is choosing fixed because it is what you drew first, then asking an alerting question of it. The quieter mistake costs more. Measure visits in fixed hourly windows and a visit running from 10:50 to 11:10 is recorded as two visits of ten minutes each. The total time is right, the count is one too high, and the mean visit length comes out low by an amount that depends on your window size rather than on your users. Nothing errors. The figure is plausible and wrong. Sliding windows fail in the opposite direction when the output has to reconcile: a one-hour window advancing every five minutes counts each event twelve times, so adding up an hour of output gives twelve times the traffic. That is fine on a dashboard and fatal on an invoice.

Session windows look cheap, one accumulator and one timer per active key, and they are until a key arrives just inside the gap every time. A key with an event every twenty-nine minutes under a thirty-minute gap never closes its session, so its accumulator grows for as long as the pipeline runs. Real systems cap session length, and a capped session has a boundary after all. The limit on the other two is cardinality rather than width: twelve regions under a fixed window hold 12×200=2,40012 \times 200 = 2{,}400 bytes, while four million user identifiers under the sliding window above hold 240 million accumulators. If the key space is unbounded, something has to expire idle keys, or the state grows forever. And none of this settles whether a window can be reported at all: a window ending at ten cannot be emitted at ten, because its events are still arriving, so whatever rule decides that no more are coming trades waiting against being wrong.

Worth keeping

  • A window is a rule about which events belong together, and the question being asked selects the rule.
  • A sliding window holds the width divided by the advance in accumulators per key, so a one-hour window advancing every minute costs sixty times what a fixed one does.
  • Key cardinality, not window width, is what usually determines whether a windowed aggregate fits.

Where this goes next

This question is one step of Counting Things as They Arrive, a course that works through its subject from the beginning. The page that teaches this part of it is Cutting Time Into Pieces, and it reads the whole way through whether or not you have an account.

What an account changes is the practice: problems standing under every idea, marked with a reason rather than a tick, in a copy of the course that is yours.

Read that pageThe whole course

Other questions people ask about this

  1. Why does my count come out doubled after the job restarts?Your count doubled because the restart replayed events the saved counter already held: the state and input position were not saved as one snapshot.
  2. Why can't I just average the old average with the new number to get a running average?Averaging the old average with the new number gives that single new value half the weight, when it deserves one share out of however many values came before.
  3. How do you count unique visitors without remembering every visitor?Turn each visitor identifier into a random-looking code, keep only a small summary of the rarest pattern seen, and scale it up; repeats change nothing and memory stays fixed.
  4. How does a streaming system know when a window is finished?It cannot know. It guesses: it takes the latest event time it has seen, subtracts an allowance you choose, and treats every window ending before that point as finished.
  5. Why is the date off by one day after I save it and read it back?You saved a calendar date as if it were a precise moment, so showing it in another time zone can move it to the day before or after.
  6. Is UTF-8 the same thing as Unicode, or what's the difference?No: Unicode assigns a number to each character, while UTF-8 is a way of writing those numbers as bytes, using one to four bytes per character.

Read alongside