Why this matters
- VaultCommerce counts orders per 5-minute tumbling window for real-time sales dashboard.
- Session windows group user clicks until 30-minute inactivity gap.
- Grace period retains window state for late-arriving events.
- Wrong window type double-counts or splits sessions incorrectly.
Window types
Tumbling: fixed, non-overlapping (5-min buckets). Hopping: overlapping with advance interval (1-min advance, 5-min size). Session: dynamic gap-based per key. VaultCommerce GMV dashboard uses tumbling; browse session analytics uses session windows with 30-min gap.
Key points
- Tumbling window — fixed size, no overlap; e.g. orders per 5 minutes
- Hopping window — sliding overlap; smoothed moving averages
- Session window — inactivity gap closes window; per-user sessions
- Grace period — lateness allowed after window end
- Suppress — control emit frequency (final results vs updates)
Grace and suppression
GraceDuration allows late events to update closed windows. suppress() emits only final results vs continuous updates. VaultCommerce sets 2-minute grace on order counts; alerts fire on suppressed final output only.
VaultCommerce rollout checklist
Before promoting changes that touch vaultcommerce.analytics.clicks.v1 fraud topology, run the staging KRaft cluster (Kafka 3.7+, Schema Registry 7.x) through a 10k events/min soak test. Compare producer request latency p99 and consumer lag per group against the pre-deploy baseline. Tumbling for fixed dashboards; session for user activity. Document the change in the internal topic registry, attach Grafana screenshots to the change ticket, and keep an engineer on lag dashboards for 30 minutes after production rollout — roll back the service release before altering broker-level settings if lag or under-replicated partitions spike.
// VaultCommerce — tumbling order count with grace
clicks.groupByKey()
.windowedBy(TimeWindows.ofSizeAndGrace(
Duration.ofMinutes(5),
Duration.ofMinutes(2))) // 2 min grace for late events
.aggregate(() -> 0L, (key, event, agg) -> agg + event.amountCents(),
Materialized.as("order-revenue-store"))
.suppress(Suppressed.untilWindowCloses(Suppressed.BufferConfig.unbounded()))
.toStream()
.to("vaultcommerce.analytics.revenue-5m.v1");
Quick recall
Everything you need if you only revisit this box.
- Tumbling for fixed dashboards; session for user activity.
- Grace handles late events after window close.
- Suppress to emit final aggregates only.
Test yourself
Answer these before moving on — recall is what makes it stick.