Skip to content

Guides

Reload a window

Replace a window of recent and future rows on every run, such as 7 days ago to 7 days ahead, with delete_insert, lookback, lookahead and lookback_from.

Some tables keep changing for a while after their rows are written, and hold future dates: orders that ship later, deliveries scheduled up to two weeks ahead, bookings. A fixed window around today, replaced on every run, keeps them right without reloading the whole table. This guide reloads from 7 days ago to 7 days ahead.

[sources.app.tables."public.deliveries"]
description = "Deliveries, one row per delivery, scheduled up to two weeks ahead."
write_strategy = "delete_insert"
cursor_column = "delivery_date"
lookback = "7d"
lookahead = "7d"
lookback_from = "now"
Setting Here
write_strategy = "delete_insert" Deletes the rows in the window it read, then inserts what it read. It needs a cursor_column and no key.
cursor_column The date or timestamp the window is on.
lookback How far back the window starts.
lookback_from = "now" Count lookback back from the time of the run, not from the destination’s maximum. Needs a lookback.
lookahead Read only cursor values before now plus this. A date cursor reads up to and including today plus that many days.

plan shows the window on the table’s reads line. On 14 November 2026:

$ sqlload plan
…
Loads (1) sqlload load
└── raw.app__deliveries delete_insert (cursor: delivery_date)
├── source postgres app public.deliveries
├── route read as Arrow -> DuckDB takes Arrow
├── reads delivery_date from 2026-11-07 (now minus lookback 7days), below 2026-11-22 (now plus lookahead 7days)
└── commits once, at the end of the read (delivery_date isn't read in order)
…

Every run reads delivery_date from 7 November up to and including 21 November, deletes those dates from the destination, and inserts what it read. A delivery deleted at the source while its date is in the window is deleted from the destination too.

  • Days are counted in UTC. A date cursor moves by whole days.

  • A timestamp cursor reads from exactly now minus lookback to now plus lookahead.

  • The first run reads the same window, so rows before it never load. To fill the table first, run --reload once (below), or backfill a range.

  • --start-cursor and --end-cursor replace the window for one run:

    $ sqlload plan --start-cursor 2026-10-01 --end-cursor 2026-11-01
    …
    ├── reads delivery_date from 2026-10-01 (--start-cursor), below 2026-11-01 (--end-cursor)
    …
  • --reload rebuilds the table from cursor_start, or from the first row, up to the lookahead:

    $ sqlload plan --reload
    …
    ├── reads delivery_date: reload, everything, below 2026-11-22 (now plus lookahead 7days)
    …
  • From 0.51.0, --reload --start-cursor rebuilds the table from that point instead, and drops older rows; see Reloading.

Without lookback_from = "now", lookback counts back from the destination’s maximum of the cursor. Each run then re-reads a window behind the newest row it already has, such as the last 2 hours, and everything after it:

[sources.app.tables."public.page_views"]
description = "Page views, one row per view."
write_strategy = "delete_insert"
cursor_column = "viewed_at"
lookback = "2h"

That suits rows that arrive late, but not a table holding future dates: its maximum is already ahead of today. lookahead works with either, and caps the read at now plus the lookahead.

  • lookahead and lookback_from = "now" need a date or timestamp cursor.
  • append takes no lookback, which would insert the window again on every run. Use delete_insert, or merge when the table has a key.
  • A files target takes neither lookahead nor lookback_from = "now": its window follows its newest partition.
  • Python tables take lookback, but not lookahead or lookback_from.

See Cursors and state for how a run decides where to read, and delete_insert for how it replaces a range.