Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Time-Window Export Mode

When to use

Use mode: time_window to export only rows within a rolling N-day window from the current timestamp. Best for:

  • Event tables where you only need the last 7/30/90 days
  • Periodic refresh of a “recent activity” dataset
  • When incremental is not suitable because you need overlapping windows

Required fields

  • time_column – the timestamp column to filter on
  • days_window – how many days back from now to include

Minimal config

source:
  type: postgres
  url: "postgresql://user:pass@host:5432/dbname"

exports:
  - name: recent_events
    query: "SELECT id, user_id, event_type, payload, created_at FROM events"
    mode: time_window
    time_column: created_at         # timestamp column to filter
    days_window: 30                 # include rows from the last 30 days
    format: parquet
    destination:
      type: local
      path: ./output

Run it

rivet check --config events.yaml
rivet run --config events.yaml --validate

What happens

  1. Rivet calculates the cutoff: NOW() - 30 days
  2. Appends WHERE created_at >= '2026-03-07 00:00:00' to your query
  3. Exports all matching rows as a fresh file
  4. No cursor is stored – each run re-evaluates the window

Unlike incremental, this mode produces overlapping data across runs (the last 30 days always overlap with yesterday’s last 30 days).

Re-runs always emit a new file (intentional)

time_window does not persist “we already exported this window” anywhere. Each rivet run re-evaluates the rolling window relative to NOW() and writes a fresh file. Two back-to-back runs inside the same minute will produce two near-identical files — same rows, different run_id / timestamp suffix. That is the contract: this mode is built for rolling recent activity (alerting, daily syncs), not for exactly-once delivery. If you need the latter, switch to mode: incremental with a cursor_column and skip_empty: true.

Downstream consumers that need deduplication should key off the id / business key inside the rows themselves, not on file name or run_id.

Time column types

By default, Rivet assumes a TIMESTAMP/DATETIME column. For Unix epoch integers, set time_column_type:

exports:
  - name: recent_events
    query: "SELECT id, user_id, event_type, created_at_epoch FROM events"
    mode: time_window
    time_column: created_at_epoch
    time_column_type: unix          # column stores Unix epoch (seconds)
    days_window: 7
    format: csv
    destination:
      type: local
      path: ./output
time_column_typeColumn typeFilter generated
timestamp (default)TIMESTAMP / DATETIMEWHERE col >= '2026-03-07 00:00:00'
unixINT / BIGINTWHERE col >= 1741305600

Common options

exports:
  - name: recent_events
    query: "SELECT id, user_id, event_type, created_at FROM events"
    mode: time_window
    time_column: created_at
    days_window: 30
    format: parquet
    compression: zstd
    skip_empty: true
    destination:
      type: local
      path: ./output

Troubleshooting

0 rows exported but the table has data – Check that days_window is large enough. Events older than the window are excluded. Also check timezones.

Duplicates across runs – This is by design. Each run exports the full window. Downstream consumers should deduplicate by primary key.

Need non-overlapping exports – Use mode: incremental with cursor_column instead.