Skip to content

docs: document adopting existing destination tables - #3325

Closed
jwhartley wants to merge 2 commits into
masterfrom
docs/pre-created-tables-partitioning
Closed

docs: document adopting existing destination tables#3325
jwhartley wants to merge 2 commits into
masterfrom
docs/pre-created-tables-partitioning

Conversation

@jwhartley

Copy link
Copy Markdown
Contributor

Attaching a materialization to a destination table that already exists was undocumented, so there was nothing to find for either case people actually hit: pre-creating a table to control DDL that Estuary does not manage, and migrating off another pipeline without dropping the destination.

Changes

  • New guide, Migrate an Existing Pipeline to Estuary at /guides/migrate-to-estuary/. Splits the empty-table case (one feature flag) from the populated-table case (also needs Exclude Flow Document and a cutover filter), since the trigger is rows existing rather than the table existing.
  • BigQuery reference: splits Table Partitioning into "Partitioning a new table", the previously undocumented pre-create path, and "Repartitioning an existing table", the pre-existing procedure. Partitioning cannot be altered after creation, so pre-creating is the only way to avoid the copy-and-rename conversion, which matters when adding many tables.
  • feature-flags: notes that allow_existing_tables_for_new_bindings is not sufficient once the table holds rows, and describes what the connector actually does to an adopted table (adds missing columns as nullable, drops NOT NULL on unselected columns, never recreates the table).
  • customize-materialization-fields: gives Exclude Flow Document its migration motivation, not just storage savings.

Two claims worth a second opinion

Both come from reading the source rather than from support threads, and both contradict guidance that has circulated internally:

  • notBefore filters on collection publish time, not on when the row changed in the source (crates/models/src/source.rs). So a timestamp copied from the outgoing tool's last sync filters nothing once the capture backfills, and the whole backfill lands in the existing table. The guide recommends Only Changes mode, or notBefore set to the backfill's completion, instead.
  • Exclude Flow Document takes effect on an existing binding's next transaction, so it does not require recreating the binding. The load template is selected from the endpoint config alone, per transaction (materialize-bigquery/transactor.go).

Notes for review

  • The page deliberately does not quote a specific error for the null-document failure, because the text differs by connector and BigQuery's is likely to change (materialize-bigquery: report NULL flow_document in load errors聽connectors#5029). It may be too vague as a result.
  • No verification or rollback section. Both were cut for length and are defensible additions.
  • All internal links were checked against declared slug: frontmatter rather than file paths, since several targets (time-travel, backfilling-data, materialization) sit at directories that do not match their URLs.
  • Sidebar is autogenerated, so the new page needs no registration.

Attaching a materialization to a table that already exists was undocumented, so
there was nothing to find for either of the two cases people hit: pre-creating a
table to control DDL that Estuary does not manage, and migrating off another
pipeline without dropping the destination.

- New guide, Migrate an Existing Pipeline to Estuary. Splits the empty-table case
  (one feature flag) from the populated-table case (also needs Exclude Flow
  Document and a cutover filter), since the trigger is rows existing rather than
  the table existing.
- BigQuery: split Table Partitioning into partitioning a new table, which is the
  previously undocumented pre-create path, and repartitioning an existing one.
  Partitioning cannot be altered after creation, so pre-creating is the only way
  to avoid the copy-and-rename conversion.
- feature-flags: note that allow_existing_tables_for_new_bindings is not
  sufficient once the table holds rows, and describe what the connector actually
  does to an adopted table (adds missing columns as nullable, drops NOT NULL on
  unselected columns, never recreates the table).
- customize-materialization-fields: give Exclude Flow Document its migration
  motivation, not just storage savings.

Two things the guide is careful about, both from reading the source rather than
from support threads:

- notBefore filters on collection publish time, not on when the row changed in
  the source, so a timestamp taken from the outgoing tool's last sync filters
  nothing once the capture backfills. Only Changes mode, or notBefore set to the
  backfill's completion, are the approaches that work.
- Exclude Flow Document takes effect on an existing binding's next transaction,
  so it does not require recreating the binding.
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

The feature-flags note said the table is "never dropped or recreated, so
partitioning, clustering, and other table-level DDL survive". That is true of the
reconciliation the connector performs when a binding attaches, and false of the
table's lifetime: a backfill truncates by default, and drops and recreates when a
selected field's type changes incompatibly, when the collection key changes, or
when always_drop_tables_on_backfill is set
(materialize-boilerplate/materializer.go:594-626).

The default onIncompatibleSchemaChange is backfill, so an incompatible schema
change reaches that path without anyone asking for a backfill, which is the case
the original wording most needed to warn about. Scoped the claim to the
reconciliation and cross-linked the backfill guide, which already documents the
triggers accurately.

Also corrects the migration guide's warning, which had truncate and
drop-and-recreate losing partitioning equally. TRUNCATE TABLE preserves it
(materialize-bigquery/client.go:155); only the drop path loses it.

And says "stored flow_document fields" rather than "stored documents" where the
storage savings are described, since that is the specific thing a backfill
clears.
@jwhartley

Copy link
Copy Markdown
Contributor Author

Scrapping this as generally we recommend backfilling in Estuary rather than trying to in-place migrate a dataflow

@jwhartley jwhartley closed this Aug 14, 2026
@jwhartley
jwhartley deleted the docs/pre-created-tables-partitioning branch August 14, 2026 05:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant