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
incrementalis not suitable because you need overlapping windows
Required fields
time_column– the timestamp column to filter ondays_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
- Rivet calculates the cutoff:
NOW() - 30 days - Appends
WHERE created_at >= '2026-03-07 00:00:00'to your query - Exports all matching rows as a fresh file
- 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_type | Column type | Filter generated |
|---|---|---|
timestamp (default) | TIMESTAMP / DATETIME | WHERE col >= '2026-03-07 00:00:00' |
unix | INT / BIGINT | WHERE 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.