Skip to main content

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:

  1. Build a primary-key hash set over the (small) source batch.
  2. Stream the (large) target one Parquet row group at a time, dropping rows whose key is in the source set.
  3. Write survivors plus the source rows into new files.
  4. 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: Falseprune_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.x as the storage/protocol layer. Correctness is guaranteed by a differential parity suite that runs the same batch sequences through real delta-rs MERGE and through deltalite.upsert and 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 MERGE silently 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

deltalite-0.1.2.tar.gz (172.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

deltalite-0.1.2-cp312-abi3-musllinux_1_2_x86_64.whl (63.8 MB view details)

Uploaded CPython 3.12+musllinux: musl 1.2+ x86-64

deltalite-0.1.2-cp312-abi3-musllinux_1_2_aarch64.whl (62.7 MB view details)

Uploaded CPython 3.12+musllinux: musl 1.2+ ARM64

deltalite-0.1.2-cp312-abi3-manylinux_2_28_x86_64.whl (65.4 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ x86-64

deltalite-0.1.2-cp312-abi3-manylinux_2_28_aarch64.whl (63.1 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ ARM64

deltalite-0.1.2-cp312-abi3-macosx_11_0_arm64.whl (17.8 MB view details)

Uploaded CPython 3.12+macOS 11.0+ ARM64

deltalite-0.1.2-cp312-abi3-macosx_10_12_x86_64.whl (18.0 MB view details)

Uploaded CPython 3.12+macOS 10.12+ x86-64

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

Hashes for deltalite-0.1.2.tar.gz
Algorithm Hash digest
SHA256 9555b17d7e57dc7e869317db4db772acfe067ad53aed2ac0699e751c401e3f02
MD5 9003b8ababd007e1bdd587c9eae605c6
BLAKE2b-256 3b1e49659fed92532267fbfc9298a16504ce8f13a26382e6355a0b43e337dade

See more details on using hashes here.

Provenance

The following attestation bundles were made for deltalite-0.1.2.tar.gz:

Publisher: build-deltalite.yml on PostHog/posthog

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file deltalite-0.1.2-cp312-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for deltalite-0.1.2-cp312-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 5b7ab6824c16a0a6fa23ce4dca15c3fdc7fbbbd98eb25dd9a290f1809842e524
MD5 55478200ab18c86b88c13d17de50f60b
BLAKE2b-256 01b2f7268ff3f7731d2421264ab2b342307893ce7e09659e98b36608ef9b5503

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file deltalite-0.1.2-cp312-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for deltalite-0.1.2-cp312-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 1eb6b872730d03367b572f8fdb876dfb08875d0d1d3a06fc35bbd40db42a6aaf
MD5 280f70268a745683e556221036eceff4
BLAKE2b-256 229c52d86d4ffb7d30dc761888b130f217e6a09d37e0ca436d3d18adba9aaed6

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file deltalite-0.1.2-cp312-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for deltalite-0.1.2-cp312-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 fc4af9d59fa944ebd906d9b395f8dcf75ff41a5c5f95540abc90914f417c9851
MD5 51a0d9993d9ef9c0c90221306987edc9
BLAKE2b-256 0560fa7c805b09f7f8d96da93572f640c3a7a256417d5a4b3a4425a7b46770a2

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file deltalite-0.1.2-cp312-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for deltalite-0.1.2-cp312-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 1c0a45ce1bcf920170d35f707018d66da9476e1c12adcc8589742c9fdce74537
MD5 db85333f560f53af1f9f25324682bcbf
BLAKE2b-256 107cda3966cf9ab0db82285dc35932dde36da665ad22808051c51841bae999f4

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file deltalite-0.1.2-cp312-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for deltalite-0.1.2-cp312-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e48f84c81c894ffb394aa92824989b64c017fc1bd4ffe4ba97b4d79d72e06829
MD5 c10cab4e3710805e6d8dbfd96abbbe3a
BLAKE2b-256 a6d5a4ca6595ad7efcc1550a39cd4a3fff67a13076db5623582100e26a6dd5c0

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file deltalite-0.1.2-cp312-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for deltalite-0.1.2-cp312-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 de3506abd5c07df8f270b6ab125a62324eda64b968614d2daf7e35a97d031123
MD5 7e5a457d471e8548db87f6ff0f1b2bf2
BLAKE2b-256 3cb02618124dc3bc8433248ffa3855bae050f6e12f0cc098857e2adc187545e5

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page