Skip to main content

Time Windows & Aggregations

Windows group messages by time intervals for aggregation. Instead of reacting to every individual message, windows let you ask questions like “How many orders in the last 5 minutes?” or “What’s the average temperature over a rolling 10-minute window?”

Window Types

LiteJoin supports three window types:

Tumbling Windows

Fixed-size, non-overlapping intervals. Each message belongs to exactly one window. When the window closes, the aggregation fires and results are emitted.
windows:
  - name: order-count
    type: tumbling
    size: 5m
    topic: orders
    query: |
      SELECT
        COUNT(*) as order_count,
        SUM(json_extract(payload, '$.amount')) as total_revenue
      FROM orders
    sink: dashboard
Time:  |--5m--|--5m--|--5m--|
       [  W1  ][  W2  ][  W3  ]
Best for: periodic reports, batch-style aggregations, non-overlapping summaries.

Sliding Windows

Fixed-size intervals that slide forward by a configurable step. Messages may appear in multiple windows.
windows:
  - name: avg-order
    type: sliding
    size: 10m
    slide: 1m
    topic: orders
    query: |
      SELECT
        AVG(json_extract(payload, '$.amount')) as avg_amount,
        COUNT(*) as count
      FROM orders
    sink: dashboard
Time:  |----10m----|
         |----10m----|
           |----10m----|
       <-1m->
Best for: moving averages, trend detection, smoothed metrics.

Session Windows

Dynamic intervals based on activity gaps. A session starts with the first message and closes when no new messages arrive within the gap duration.
windows:
  - name: user-session
    type: session
    gap: 30m
    topic: user_events
    query: |
      SELECT
        COUNT(*) as event_count,
        MIN(timestamp) as session_start,
        MAX(timestamp) as session_end
      FROM user_events
    sink: analytics
Time:  |msg|  |msg|msg|     |--- gap > 30m ---|  |msg|msg|
       [    session 1    ]                        [ session 2 ]
Best for: user sessions, burst detection, grouping related events.

Configuration

Common Fields

FieldTypeRequiredDescription
namestringyesUnique name for the window.
typestringyestumbling, sliding, or session.
topicstringyesTopic to aggregate.
querystringyesSQL aggregation query.
sinkstringyesSink to emit results to.

Type-Specific Fields

FieldApplies ToTypeDescription
sizetumbling, slidingdurationWindow size (e.g., 5m, 1h).
slideslidingdurationSlide interval. Must be ≤ size.
gapsessiondurationInactivity gap to close a session.

Result Format

Window results are emitted as JoinResult objects, the same format as join results:
{
  "query": "order-count",
  "key": "window_1740268800_1740269100",
  "rows": [
    {
      "order_count": 42,
      "total_revenue": 3850.00
    }
  ],
  "emit_at": "2026-02-22T10:05:00Z"
}

Combining Windows with Joins

You can use window aggregations as inputs to joins. For example, aggregate orders per region, then join with region metadata:
windows:
  - name: orders-by-region
    type: tumbling
    size: 5m
    topic: orders
    query: |
      SELECT
        json_extract(payload, '$.region') as region,
        COUNT(*) as count,
        SUM(json_extract(payload, '$.amount')) as revenue
      FROM orders
      GROUP BY json_extract(payload, '$.region')
    sink: dashboard

Best Practices

  1. Choose the right window type. Tumbling for periodic reports, sliding for moving averages, session for activity-based grouping.
  2. Keep size reasonable. Larger windows hold more data in memory. Start with 5–15 minute windows.
  3. Use GROUP BY for segmentation. Split aggregations by a dimension (region, user type, status) for richer insights.
  4. Test with Studio. Use the visual windowing controls in LiteJoin Studio to experiment without writing complex config.