Configuration
The components of a configuration file are:
db
Connection details for the target database. Example:
db:
backend: mariadb
hostname: 127.0.0.1
port: 3306
username: root
password: adminbackend defaults to mariadb when omitted. Supported backend names are:
mariadb- the default and currently complete production backend.xtdb- supported XTDB adapter. Install with thextdboptional dependency before creating an XTDB engine. The optional dependency includes the binary psycopg wrapper for pgwire and the ADBC FlightSQL driver for Arrow-native bulk ingest.mssql- currently reserved for a future MS SQL adapter.
XTDB uses two ports when both backend paths are enabled:
portdefaults to5432for the pgwire/SQLAlchemy path.adbc_portdefaults to9832for the ADBC/FlightSQL path.
XTDB writes are chunked by max_rows_per_insert, which defaults to 10000. This bounds the size of each final insert/ingest transaction after staging, deduplication, transforms, foreign-key handling, and unchanged-row filtering have already run. Lower this value for smaller XTDB nodes or raise it only after load testing retained/replay workloads.
ingestion
Dataset execution is bounded and preserves ordering for datasets that write to the same tables. Independent datasets can run concurrently:
ingestion:
max_workers: 2
queue_size: 2Both values default to 1. Increase max_workers only after confirming the database pool and target database can sustain the additional concurrent writes.
table_configs
A collection of tables that will be managed by this configuration. Example:
table_configs:
- schema: test
name: simple_table
columns:
- id
- another_id
- [ col_double, col_varchar ]
primary_keys:
- id
foreign_keys:
- name: another_id
references:
table: another_table
column: id
is_temporal: true
delta_config:
drop_unchanged_rows: true
on_duplicate_key: take_last
prefill_nulls_with_default: false
row_finality: dropoutThe main section defines usual properties of the table, including the name of the table, the column names, plus any primary and foreign keys.
A flag is_temporal indicates whether the table uses system versioning. Uploading of temporal data is done in two parts. First the data is staged to a temporary table, allowing some computations to be done before modifying the target table. Specifically:
- rows can be dropped from the staged table if they have not changed, meaning the as-of date of the associated data would not be modified.
- sometimes within a single batch of data, multiple versions of the same row may be present. The
primary_keydefines how rows are tested for ‘equality’ and theon_duplicate_keyoption controls how duplicates are handled. - the
row_finalityoption controls what happens when a row is no longer present in the data-batch.
column_definitions
A set of typed column definitions referenced by table_configs and datasets section of the files.
column_definitions:
- { name: rating, data_type: INT, header: Rating, nullable: false, default_value: 0 }
- {
name: price_usd,
data_type: 'DECIMAL(10,4)',
transforms: {
try_to_usd: [ 'Price', 'Year' ]
}
}
- { name: month, data_type: VARCHAR(2), header: Month }
- { name: year, data_type: INT, header: Year }Each column definition defines a column to be created in the staging table. This is either a mapping from a column in the source data file (called header when the name is different), or a derived column according to some user-defined transformation. An example of how to define a transformation is the price_usd column above, with full details given in the example notebook.
datasets
This is a set of data sources and pipelines, describing where to look for new data, and how to process it into the defined tables. Example:
datasets:
- name: turkey_food_prices
delta_table_schema: test
scrape_limit: ~
search_paths:
- root_path: ../_testdata_dataset_data
file_include: ['turkey_food_prices.csv']
is_enabled: true
timestamp:
source_tz: Europe/London
method: mtime
- ...
pipeline:
- table: unit_info
columns:
- id<um_id!
- name<um_name!
- table: food_prices
type: primary
columns:
- product_id!
- um_id!
- price!
- price_usd!The search_paths section defines where to find the data. The example above uses the timestamp.method of mtime to set the as-of date of the data.
The pipeline section contains a sequence of tasks that are run in order. The example above demonstrates two tasks:
For flattened payloads, the pipeline is also the authoritative input schema. Every source column must be declared. Its input type is resolved from ingestion_data_type, falling back to target_data_type and then the target table column type. Declare ingestion_data_type only when the raw type differs from the target type. Undeclared columns, incompatible values, missing required columns, conflicting declarations, and nulls in non-nullable columns fail before payloads are combined or staged.
Use column_type: input_only for a declared, typed source field that must be accepted but not staged or persisted:
columns:
- {source: record.id, target: id}
- {source: record.measurement, target: measurement, ingestion_data_type: DOUBLE}
- {source: record.unused_note, column_type: input_only, ingestion_data_type: VARCHAR(64)}Transformation results and staging types continue to come from target_data_type or the target table schema, so a separate output schema is not required. The older dsv_only spelling remains supported for existing DSV configurations.
Task 1: Unit Info Table
This task populates the unit_info table:
- Reads
um_idandum_namecolumns from the staging table - Renames them using
<operator:um_idtoidum_nametoname
- Both columns are required (marked with
!)
Task 2: Food Prices Table
This task populates the food_prices table:
- Reads
product_id,um_id,price, andprice_usdcolumns - Maps directly to matching column names (no renaming needed)
- All columns are required (marked with
!) - Table is marked as
type: primaryfor system versioning - Note: Currently only one primary task is allowed per pipeline
Valid time
Datasets can map source validity columns onto a backend’s valid-time metadata with valid_time entries:
datasets:
- name: source_event_stream
delta_table_schema: source
valid_time:
- schema: source
table: events
from_column: event_timestamp
pipeline:
- schema: source
table: events
type: primary
columns:
- {source: id, target: id}
- {source: event_timestamp, target: event_timestamp}The configured from_column identifies when a row becomes valid. An optional to_column identifies when the row stops being valid for rows with an explicit validity window:
valid_time:
- schema: overrides
table: data_override_operations
from_column: valid_from
to_column: valid_toMapped valid-time source columns are required. Ingest fails if a configured from_column or to_column is missing or contains null values, because falling back to upload/system time would change the source semantics.
Backends decide how to materialize the backend-neutral valid-time contract. The XTDB backend maps from_column to _valid_from and to_column to _valid_to. SQL/MariaDB ingestion validates the configured source columns in the staging table, but does not materialize separate valid-time metadata.
Override Ledgers
polars-hist-db exposes a backend-independent override ledger contract for applications that need append-only user-authored corrections without mutating canonical source-feed tables.
from polars_hist_db.overrides import (
OverrideLedgerConfig,
build_override_table_config,
build_override_valid_time_config,
)
config = OverrideLedgerConfig(
schema="overrides",
table="data_override_operations",
)
table_config = build_override_table_config(config)
valid_time = build_override_valid_time_config(config)Equivalent YAML shape for downstream applications:
override_ledgers:
- schema: overrides
table: data_override_operations
valid_time:
from_column: valid_from
to_column: valid_tovalid_from and valid_to are explicit business-validity columns. XTDB also has built-in _valid_from and _valid_to columns, but applications should not depend on those system columns as the only representation of user correction windows.
The generated table includes owner, actor, feed, entity, field path, operation type, typed JSON value, observed canonical value, stale-source flag, validity window, reason, comment, and metadata fields. The same table contract is intended to work with MariaDB and XTDB adapters.