F4.08 · part 2 of 3
SQLite & PostgreSQL
Because the high bits of the id are a timestamp, a window of time is a contiguous window of ids.
To find every user created in a span, you do not need a created_at column or a second
index: compute the Snowflake at the start of the window and the Snowflake at the end, and ask for
id >= min AND id < max. The primary-key index already answers it.
Pick a window. The bounds are computed the same way the generator makes ids —
(ms − epoch) << 22 — so the query is exact. Select a range.
A time window is an id range
The lower bound is the smallest id that could be minted at or after the window opens; the upper bound is the smallest id at or after it closes. Every row in between was created in the window. Select a range to compute its bounds and the query.
Time window · select one
window: 2026-05
served by: the primary-key index
No timestamp column, no second index: the bounds are pure arithmetic on the dates, and the primary-key B-tree already stores rows in the order the query wants them.
Advanced: one index, two queries
The bound is (ms − epoch) << 22 — the timestamp shifted into place
with the worker and sequence bits zeroed, which is the smallest id any worker could mint at that millisecond.
So id >= min admits every id from the window’s first millisecond onward, and
id < max stops at the next window’s first millisecond — a half-open
range that misses nothing and double-counts nothing, across all 1024 workers. The same primary-key index that
does point lookups serves this scan as a contiguous read, so a point fetch and a time range share one
structure.
It is identical in SQLite and PostgreSQL: SQLite holds the id in its INTEGER class (up to 8 bytes),
PostgreSQL in a bigint, and the comparison is numeric in both. The
EchoData.Snowflake helpers min_for_time/1 and
max_for_time/1 produce the two bounds, so the query reads as a date range while the
database sees integers.
# a date range becomes an id range — the PK index serves it min = EchoData.Snowflake.min_for_time("2026-05-01") # => 308392073625600000 max = EchoData.Snowflake.max_for_time("2026-06-01") # => 319626097459200000 from(u in User, where: u.id >= ^min and u.id < ^max) # every user created in May 2026 — no created_at column, no second index
a date window
“Everything created in May” — a span of time.
a contiguous id range
id >= min AND id < max, answered by the primary-key index.
Next: Redis keys — namespaced string keys, and how edge validation sheds abusive traffic before the cache.
References
Primary sources for this lesson, and where it connects in the course.
Sources
- SQLite — Datatypes — INTEGER comparison and ordering.
- PostgreSQL — Index Types — the B-tree that serves both point and range queries.
- Ecto.Query — expressing the half-open id range in Elixir.
Related in this course
- F4.08 · Branded ids & persistence — the module hub.
- F4.07.2 · The Snowflake bigint — why time sits in the high bits.
- F4 · Algorithms & Data Structures