Streaming partition upsert for Delta tables, replacing delta-rs SQL MERGE
Project description
deltalite
Streaming, partition-level upsert for Delta Lake tables
that replaces delta-rs's SQL MERGE with a bounded-memory merge engine. Memory
is bounded by the size of the incoming batch and a few concurrency knobs —
never by the size of the target table.
delta-rs stays the storage and protocol layer (transaction log, checkpoints, Parquet writing, Add-action statistics, S3 conditional-put commits, conflict resolution). deltalite replaces only the merge execution.
import deltalite
table = deltalite.DeltaLiteTable.open("s3://bucket/my_table")
stats = table.upsert(record_batch, primary_keys=["id"], partition_key="day")
print(f"v{stats.version}: +{stats.rows_inserted} / ~{stats.rows_updated}")
Why
delta-rs MERGE executes a DataFusion hash join whose memory scales with the
scanned target, and it can deadlock under a bounded memory pool
(delta-io/delta-rs#4614).
For a large, slowly-changing table merged against a comparatively small batch —
the typical incremental-sync shape — that means either OOM risk or a hang.
deltalite takes a different route:
- Build a primary-key hash set over the (small) source batch.
- Stream the (large) target one Parquet row group at a time, dropping rows whose key is in the source set.
- Write survivors plus the source rows into new files.
- Commit every touched partition in one atomic Delta commit.
Peak memory is bounded by the source batch and the concurrency knobs, not by
the table. In validation, resident memory stayed flat from 62k- to 1M-row
partitions (~4× below MERGE) at matching write volume, via exact
content-based file selection.
Installation
pip install deltalite
# or
uv add deltalite
Prebuilt cp312-abi3 wheels are published for manylinux (2_28) and musllinux
on x86_64/aarch64, and macOS on arm64/x86_64. A single wheel works on any
CPython 3.12 or newer. No Rust toolchain is needed to install.
Usage
upsert accepts anything with the pyarrow C-stream interface — a
pyarrow.Table, a RecordBatch, or a RecordBatchReader:
import pyarrow as pa
import deltalite
table = deltalite.DeltaLiteTable.open(
"s3://bucket/events",
storage_options={
"AWS_REGION": "us-east-1",
"AWS_ACCESS_KEY_ID": "...",
"AWS_SECRET_ACCESS_KEY": "...",
},
)
batch = pa.table({
"id": [1, 2, 3],
"day": ["2026-01-01", "2026-01-01", "2026-01-02"],
"val": ["a", "b", "c"],
})
stats = table.upsert(
batch,
primary_keys=["id"],
partition_key="day", # omit for an unpartitioned table
commit_metadata={"source": "my-sync"},
)
print(stats)
# UpsertStats(version=42, partitions_touched=2, files_added=2, files_removed=1, ...)
Rows in the batch whose primary key already exists are replaced; new keys
are inserted. Deletes are not expressed through upsert — it is an
insert-or-replace by key. Duplicate primary keys within a single batch are
rejected (raising DeltaLiteError) rather than silently double-inserted.
API
DeltaLiteTable
| Method | Description |
|---|---|
DeltaLiteTable.open(uri, storage_options=None) |
Open an existing Delta table. storage_options is the usual object-store dict (S3/GCS/Azure/local). |
DeltaLiteTable.is_deltatable(uri, storage_options=None) |
True if a Delta table exists at uri. |
.upsert(data, primary_keys, partition_key=None, **opts) |
Insert-or-replace data by key. Returns UpsertStats. See knobs below. |
.version() |
Current table version (int). |
.reload() |
Reload the table state from the log. |
.schema_arrow() |
Table schema as a pyarrow Schema. |
.partition_columns() |
Partition column names (list[str]). |
.file_uris() |
URIs of the table's active data files. |
.history(limit) |
Recent commit history entries. |
UpsertStats
Returned by upsert. Fields: version, partitions_touched, files_added,
files_removed, files_carried_over, files_probed, rows_updated,
rows_inserted, rows_copied, source_rows, null_pk_rows.
Exceptions
All inherit from DeltaLiteError, so you can catch the base or branch on kind:
| Exception | Raised when |
|---|---|
DeltaLiteError |
Base class / generic failure. |
DeltaLiteCommitConflictError |
Concurrent commit won the conditional-put race (retry-exhausted). |
DeltaLiteSchemaMismatchError |
Batch schema is incompatible with the table. |
DeltaLiteTableNotFoundError |
No Delta table at the URI. |
DeltaLiteUnsupportedTableError |
Table uses a feature deltalite can't handle (e.g. deletion vectors, column mapping). |
DeltaLiteSourceTooLargeError |
Batch exceeds max_source_bytes (see below). |
Operational knobs
Per-call — keyword arguments to upsert (defaults in parentheses):
| Argument | Default | Purpose |
|---|---|---|
max_parallel_partitions |
2 |
Partitions merged concurrently. |
max_parallel_files |
4 |
Files read concurrently within a partition. |
max_buffered_bytes |
64 MiB |
Output buffered in memory before flushing. |
prune_strategy |
"probe" |
"probe" skips files that can't contain a source key; "none" scans all. |
skip_unmatched_files |
True |
Convenience toggle: False ≡ prune_strategy="none". |
probe_concurrency |
8 |
Concurrent statistics/probe reads. |
read_batch_size |
8192 |
Row-group read batch size. |
target_file_size |
table setting, else 100 MiB | Output file size target. |
max_source_bytes |
2 GiB |
Oversized-batch guard (0 disables). |
multipart_threshold / multipart_part_size |
64 MiB / 16 MiB |
Multipart upload thresholds (0 threshold disables). |
commit_max_retries |
15 |
Conditional-put commit retry budget. |
commit_metadata |
None |
Extra key/values recorded in the Delta commit. |
Process-global — environment variables, enforced on top of the per-call knobs so that many concurrent upsert threads in one process cannot multiply the budgets:
DELTALITE_PROCESS_MAX_PARALLEL_PARTITIONS (8),
DELTALITE_PROCESS_MAX_PARALLEL_FILES (16),
DELTALITE_PROCESS_MAX_BUFFERED_BYTES (256 MiB),
DELTALITE_MAX_SOURCE_BYTES, DELTALITE_MULTIPART_THRESHOLD_BYTES,
DELTALITE_MULTIPART_PART_SIZE_BYTES.
Metrics
deltalite emits via the Rust metrics facade (static
labels only): deltalite_upserts_total (outcome, prune_strategy,
error_kind), deltalite_upsert_duration_seconds,
deltalite_files_{added,removed,carried_over,probed}_total, and
deltalite_rows_{updated,inserted,copied}_total.
Compatibility & status
- Built against
deltalake(delta-rs)0.32.xas the storage/protocol layer. Correctness is guaranteed by a differential parity suite that runs the same batch sequences through real delta-rsMERGEand throughdeltalite.upsertand asserts identical logical content — not by version equality. - Not supported: tables with deletion vectors or column mapping (detected
and raised as
DeltaLiteUnsupportedTableError), and SCD2 merges. - deltalite rejects duplicate source primary keys that
MERGEsilently double-inserts — check pre-existing data if you migrate an existing pipeline.
This package is developed in the PostHog monorepo
under rust/deltalite/. Issues and source live there.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file deltalite-0.1.2.tar.gz.
File metadata
- Download URL: deltalite-0.1.2.tar.gz
- Upload date:
- Size: 172.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9555b17d7e57dc7e869317db4db772acfe067ad53aed2ac0699e751c401e3f02
|
|
| MD5 |
9003b8ababd007e1bdd587c9eae605c6
|
|
| BLAKE2b-256 |
3b1e49659fed92532267fbfc9298a16504ce8f13a26382e6355a0b43e337dade
|
Provenance
The following attestation bundles were made for deltalite-0.1.2.tar.gz:
Publisher:
build-deltalite.yml on PostHog/posthog
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
deltalite-0.1.2.tar.gz -
Subject digest:
9555b17d7e57dc7e869317db4db772acfe067ad53aed2ac0699e751c401e3f02 - Sigstore transparency entry: 2280953307
- Sigstore integration time:
-
Permalink:
PostHog/posthog@611346e147ab0118a1805b3cade696aa5f9501f0 -
Branch / Tag:
refs/pull/74682/merge - Owner: https://github.com/PostHog
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-deltalite.yml@611346e147ab0118a1805b3cade696aa5f9501f0 -
Trigger Event:
pull_request
-
Statement type:
File details
Details for the file deltalite-0.1.2-cp312-abi3-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: deltalite-0.1.2-cp312-abi3-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 63.8 MB
- Tags: CPython 3.12+, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b7ab6824c16a0a6fa23ce4dca15c3fdc7fbbbd98eb25dd9a290f1809842e524
|
|
| MD5 |
55478200ab18c86b88c13d17de50f60b
|
|
| BLAKE2b-256 |
01b2f7268ff3f7731d2421264ab2b342307893ce7e09659e98b36608ef9b5503
|
Provenance
The following attestation bundles were made for deltalite-0.1.2-cp312-abi3-musllinux_1_2_x86_64.whl:
Publisher:
build-deltalite.yml on PostHog/posthog
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
deltalite-0.1.2-cp312-abi3-musllinux_1_2_x86_64.whl -
Subject digest:
5b7ab6824c16a0a6fa23ce4dca15c3fdc7fbbbd98eb25dd9a290f1809842e524 - Sigstore transparency entry: 2280953325
- Sigstore integration time:
-
Permalink:
PostHog/posthog@611346e147ab0118a1805b3cade696aa5f9501f0 -
Branch / Tag:
refs/pull/74682/merge - Owner: https://github.com/PostHog
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-deltalite.yml@611346e147ab0118a1805b3cade696aa5f9501f0 -
Trigger Event:
pull_request
-
Statement type:
File details
Details for the file deltalite-0.1.2-cp312-abi3-musllinux_1_2_aarch64.whl.
File metadata
- Download URL: deltalite-0.1.2-cp312-abi3-musllinux_1_2_aarch64.whl
- Upload date:
- Size: 62.7 MB
- Tags: CPython 3.12+, musllinux: musl 1.2+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1eb6b872730d03367b572f8fdb876dfb08875d0d1d3a06fc35bbd40db42a6aaf
|
|
| MD5 |
280f70268a745683e556221036eceff4
|
|
| BLAKE2b-256 |
229c52d86d4ffb7d30dc761888b130f217e6a09d37e0ca436d3d18adba9aaed6
|
Provenance
The following attestation bundles were made for deltalite-0.1.2-cp312-abi3-musllinux_1_2_aarch64.whl:
Publisher:
build-deltalite.yml on PostHog/posthog
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
deltalite-0.1.2-cp312-abi3-musllinux_1_2_aarch64.whl -
Subject digest:
1eb6b872730d03367b572f8fdb876dfb08875d0d1d3a06fc35bbd40db42a6aaf - Sigstore transparency entry: 2280953314
- Sigstore integration time:
-
Permalink:
PostHog/posthog@611346e147ab0118a1805b3cade696aa5f9501f0 -
Branch / Tag:
refs/pull/74682/merge - Owner: https://github.com/PostHog
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-deltalite.yml@611346e147ab0118a1805b3cade696aa5f9501f0 -
Trigger Event:
pull_request
-
Statement type:
File details
Details for the file deltalite-0.1.2-cp312-abi3-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: deltalite-0.1.2-cp312-abi3-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 65.4 MB
- Tags: CPython 3.12+, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fc4af9d59fa944ebd906d9b395f8dcf75ff41a5c5f95540abc90914f417c9851
|
|
| MD5 |
51a0d9993d9ef9c0c90221306987edc9
|
|
| BLAKE2b-256 |
0560fa7c805b09f7f8d96da93572f640c3a7a256417d5a4b3a4425a7b46770a2
|
Provenance
The following attestation bundles were made for deltalite-0.1.2-cp312-abi3-manylinux_2_28_x86_64.whl:
Publisher:
build-deltalite.yml on PostHog/posthog
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
deltalite-0.1.2-cp312-abi3-manylinux_2_28_x86_64.whl -
Subject digest:
fc4af9d59fa944ebd906d9b395f8dcf75ff41a5c5f95540abc90914f417c9851 - Sigstore transparency entry: 2280953359
- Sigstore integration time:
-
Permalink:
PostHog/posthog@611346e147ab0118a1805b3cade696aa5f9501f0 -
Branch / Tag:
refs/pull/74682/merge - Owner: https://github.com/PostHog
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-deltalite.yml@611346e147ab0118a1805b3cade696aa5f9501f0 -
Trigger Event:
pull_request
-
Statement type:
File details
Details for the file deltalite-0.1.2-cp312-abi3-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: deltalite-0.1.2-cp312-abi3-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 63.1 MB
- Tags: CPython 3.12+, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1c0a45ce1bcf920170d35f707018d66da9476e1c12adcc8589742c9fdce74537
|
|
| MD5 |
db85333f560f53af1f9f25324682bcbf
|
|
| BLAKE2b-256 |
107cda3966cf9ab0db82285dc35932dde36da665ad22808051c51841bae999f4
|
Provenance
The following attestation bundles were made for deltalite-0.1.2-cp312-abi3-manylinux_2_28_aarch64.whl:
Publisher:
build-deltalite.yml on PostHog/posthog
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
deltalite-0.1.2-cp312-abi3-manylinux_2_28_aarch64.whl -
Subject digest:
1c0a45ce1bcf920170d35f707018d66da9476e1c12adcc8589742c9fdce74537 - Sigstore transparency entry: 2280953348
- Sigstore integration time:
-
Permalink:
PostHog/posthog@611346e147ab0118a1805b3cade696aa5f9501f0 -
Branch / Tag:
refs/pull/74682/merge - Owner: https://github.com/PostHog
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-deltalite.yml@611346e147ab0118a1805b3cade696aa5f9501f0 -
Trigger Event:
pull_request
-
Statement type:
File details
Details for the file deltalite-0.1.2-cp312-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: deltalite-0.1.2-cp312-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 17.8 MB
- Tags: CPython 3.12+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e48f84c81c894ffb394aa92824989b64c017fc1bd4ffe4ba97b4d79d72e06829
|
|
| MD5 |
c10cab4e3710805e6d8dbfd96abbbe3a
|
|
| BLAKE2b-256 |
a6d5a4ca6595ad7efcc1550a39cd4a3fff67a13076db5623582100e26a6dd5c0
|
Provenance
The following attestation bundles were made for deltalite-0.1.2-cp312-abi3-macosx_11_0_arm64.whl:
Publisher:
build-deltalite.yml on PostHog/posthog
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
deltalite-0.1.2-cp312-abi3-macosx_11_0_arm64.whl -
Subject digest:
e48f84c81c894ffb394aa92824989b64c017fc1bd4ffe4ba97b4d79d72e06829 - Sigstore transparency entry: 2280953318
- Sigstore integration time:
-
Permalink:
PostHog/posthog@611346e147ab0118a1805b3cade696aa5f9501f0 -
Branch / Tag:
refs/pull/74682/merge - Owner: https://github.com/PostHog
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-deltalite.yml@611346e147ab0118a1805b3cade696aa5f9501f0 -
Trigger Event:
pull_request
-
Statement type:
File details
Details for the file deltalite-0.1.2-cp312-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: deltalite-0.1.2-cp312-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 18.0 MB
- Tags: CPython 3.12+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de3506abd5c07df8f270b6ab125a62324eda64b968614d2daf7e35a97d031123
|
|
| MD5 |
7e5a457d471e8548db87f6ff0f1b2bf2
|
|
| BLAKE2b-256 |
3cb02618124dc3bc8433248ffa3855bae050f6e12f0cc098857e2adc187545e5
|
Provenance
The following attestation bundles were made for deltalite-0.1.2-cp312-abi3-macosx_10_12_x86_64.whl:
Publisher:
build-deltalite.yml on PostHog/posthog
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
deltalite-0.1.2-cp312-abi3-macosx_10_12_x86_64.whl -
Subject digest:
de3506abd5c07df8f270b6ab125a62324eda64b968614d2daf7e35a97d031123 - Sigstore transparency entry: 2280953334
- Sigstore integration time:
-
Permalink:
PostHog/posthog@611346e147ab0118a1805b3cade696aa5f9501f0 -
Branch / Tag:
refs/pull/74682/merge - Owner: https://github.com/PostHog
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-deltalite.yml@611346e147ab0118a1805b3cade696aa5f9501f0 -
Trigger Event:
pull_request
-
Statement type: