Version Binding
Version binding lets a query state the relation versions it expects.
That makes it a schema-contract feature.
It is especially useful when:
- an application was written against a specific table version
- you want queries to fail fast when storage no longer matches that expectation
- you want joins to assert that both sides of the query still satisfy the version assumptions they were written against
Basic form
Version binding is attached directly to relation references:
SELECT *
FROM public.users@=3That query is saying:
"Run this query only if
public.userssatisfies the version spec=3."
Version spec operators
Common forms include:
public.users@=3
public.users@<3
public.users@>4
public.users@<=3
public.users@>=4
public.users@=3_4Those forms are part of the parser surface and are exercised in tests.
Join example
Version binding becomes especially valuable when multiple relations participate in a query.
SELECT
a.id,
b.name
FROM public.vja@=1 AS a
LEFT JOIN public.vjb@=1 AS b
ON a.rel = b.idHow to read this:
- the query expects
public.vjaat relation version1 - the query expects
public.vjbat relation version1 - if either side no longer satisfies that contract, the query should not silently continue as if nothing changed
That is why "version binding" is a better phrase here than "version syntax." It is about explicit version control at the query boundary.
Why version binding exists
Most schema drift bugs are painful because they fail too late:
- a query still parses
- a deployment still boots
- but the semantics the application assumed are no longer true
Version binding gives you a way to express:
"This query is coupled to this relation version. If the storage side has moved, fail visibly."
What version binding is not
This point is critical.
Version binding is not the same thing as historical row snapshotting.
It does not mean:
- "show me the rows as they were when version 3 existed"
It means:
- "run this query only if the relation version assumptions are satisfied"
For historical replay, use FlashQL's point-in-time boot support with versionStop.
Version binding vs point-in-time replay
| Feature | What it means |
|---|---|
| version binding in a query | "this query assumes these relation versions" |
versionStop at boot | "boot the local engine at this historical relation-version boundary" |
These features complement each other, but they are not interchangeable.
FlashQL-specific support
Version binding is a FlashQL-oriented capability today because it depends on relation-version knowledge inside the local storage/runtime layer.
You will most commonly encounter it in:
- FlashQL queries
- FlashQL joins
- FlashQL historical/branching workflows
Example: bind and then boot historically
const db = new FlashQL({
keyval,
versionStop: 'public.snap_tbl@1',
});
await db.connect();
const result = await db.query(`
SELECT id
FROM public.snap_tbl@=1
ORDER BY id
`);In that shape:
versionStopchooses the historical replay boundary@=1asserts the query's relation-version expectation
When to reach for version binding
Use it when:
- you care about schema/version safety more than silent compatibility
- you are building version-aware local apps on FlashQL
- you want joins to assert compatibility across multiple versioned relations
