/

Comparison

Peak Memory of 7 Replication Tools on 298M Rows (2026)

Intergalactic Data Labs

โ€”

โ€”

11 min read

Table of contents

Summarize

Seven replication tools and one pg_dump baseline copied the same 298 million Postgres rows in the public 2026-08-31 cohort, and their peak memory spans roughly three orders of magnitude. The largest footprint belongs to dlt at 45.5 GiB. The table below holds every tool's peak memory, CPU seconds, wall time, and throughput from the result files, read on October 15, 2026.

Tool

Version in the run

Peak memory

CPU seconds

Wall time

Rows per second

Filament

standalone latest tag

2.97 GiB

377

115 s

2,597,498

dlt

1.29.0 on Python 3.11

45.54 GiB

728

296 s

1,007,711

Debezium Server

3.6.1.Final, JDBC sink

15.70 GiB

11,658

6,559 s

45,476

Airbyte

source 3.8.1, destination 3.0.13

14.45 GiB

13,703

10,393 s

28,698

ingestr

latest tag, v1 Go build

4.83 GiB

157

611 s

488,233

PeerDB

stable-v0.37.0, 7 containers

1.20 GiB

3,270

415 s

718,368

Sling

v1.5.20, free CLI

103 MiB

2,211

1,053 s

283,188

pg_dump to psql (baseline)

postgres 16 image

15 MiB

63

489 s

610,267

Disclosure, this site belongs to Galaxy, the company behind Filament. The same company runs and publishes this benchmark, and every cell above is the median repetition from the result files, with memory summed across each tool's containers and rounded.

How the memory was measured

Every figure is a Docker stats sample, not a process RSS, taken on one host with two RDS instances as source and target. The methodology states the rule plainly, "Memory is each container's highest sample".

Item

Value in the run

Host

AWS c7i.16xlarge, 64 vCPU, 128 GiB, Ubuntu 24.04

Databases

Two RDS db.m6i.8xlarge, Postgres 16, same availability zone

Dataset

NYC Taxi, 12 months, 298,270,427 rows in two tables

Sampling

Docker stats every 100 ms, peak per container

CPU

Total container CPU time over the measured window

Timer

Starts at the transfer trigger, ends when the adapter reports done

Verification

Row counts per destination table, all passed

Repetitions

Three, except Debezium and Airbyte with one

Three caveats follow. Summed container peaks "may have occurred at different times", so a stack figure such as PeerDB's is an upper bound. The Airbyte figure includes a 28 MiB harness driver and excludes Airbyte's own server, worker, and Temporal services, which the adapter omits per the README. Units are binary GiB, converted from the bytes in the files.

The last caveat is Debezium. The README says "The full-load benchmark measures its initial snapshot, not the steady-state streaming workload it is primarily designed for", so its row is a one-time snapshot through the JDBC sink. The public results page reports Airbyte's single largest container, while this article sums all three.

Why does dlt use 45 GiB on a full load?

dlt holds about 164 bytes of peak memory per row moved, and its own docs explain where it goes. This is the Python library from dltHub, not Databricks Delta Live Tables. Its performance guide says "dlt buffers data in memory to speed up processing and uses the file system to pass data between the extract and normalize stages."

dlt setting

Value in the run

What the docs say it does

Backend

connectorx, arrow_stream

Reads rows in Rust, skips SQLAlchemy

Extract batch size

100,000 rows

Rows per Arrow batch from the source

buffer_max_items

200,000 items

Items held in memory before a file write

file_max_bytes

3,000,000 bytes

Rotates intermediary files so stages run in parallel

Normalize workers

16 processes, spawn

Process pool that builds load packages

Load workers

16 threads

Threads each loading one file

Loader format

CSV, no compression

File format the Postgres destination loads

The values come from the result file and the adapter's environment, and the descriptions from the performance guide and the sql_database configuration page. The container is one process tree, so every normalize process and load thread counts toward one peak.

The guide also warns that without file rotation "dlt will still create a single intermediary file to normalize and a single file to load", which is why the run rotated files at 3 MB. Rotation gave dlt the second fastest wall time in the cohort, and running sixteen normalize processes over Arrow batches cost the largest footprint by a factor of three.

Where the memory goes in multi-container stacks

PeerDB spreads a small total across seven services, while Airbyte concentrates almost everything in its source connector. These are the two tools that ran as several containers.

Stack

Container

Peak memory

CPU seconds

PeerDB

flow-worker

755 MiB

3,249

PeerDB

catalog (Postgres 16)

253 MiB

6

PeerDB

temporal

142 MiB

15

PeerDB

snapshot-worker, flow-api, server, temporal-cli

under 40 MiB each

under 1 each

Airbyte

source-postgres 3.8.1

12.82 GiB

2,413

Airbyte

destination-postgres 3.0.13

1.60 GiB

10,312

Airbyte

harness driver (docker cli)

28 MiB

978

Airbyte's source container reached 80 percent of the 16 GiB limit the methodology gave each connector. The scaling guide explains why. It says "The orchestrator buffers records between the source and destination, so database tables with large rows or wide schemas need more memory than the defaults provide."

The destination side tells a different story. Since version 3.0.0 the Postgres destination writes "directly to final tables without using intermediate raw tables", per its docs page. It burned four times the CPU of the source while holding a fraction of its memory, and the same page still asks users to stay under about 10 GB.

How much of its 64 GiB heap did Debezium use?

Just under a quarter. The run gave Debezium Server a JVM heap of -Xms8g -Xmx64g and raised the queue and batch settings above their defaults, and the snapshot peaked at 15.70 GiB.

Debezium setting

Documented default

Value in the run

max.batch.size

2,048

8,192

max.queue.size

8,192

32,768

max.queue.size.in.bytes

0, no limit

1,073,741,824

snapshot.fetch.size

10,240

10,240

snapshot.max.threads

1

8

JVM heap

not documented

64 GiB

Defaults come from the Postgres connector reference, which describes the queue as a buffer that "can provide backpressure", and the run values from the result file. The heap ceiling is a harness choice, since the Debezium Server docs state no default, so a smaller cap would give a smaller figure and possibly a longer run.

Two facts limit how far this row can be read. The Debezium file holds one repetition rather than three, and the figure is a snapshot rather than the streaming workload Debezium is built for. It is a fair measure of what a Debezium backfill costs on a host, and nothing more.

What bounded the three smallest footprints

Sling, the pg_dump pipe, and the PeerDB stack all stayed under 1.3 GiB, and in each case the bound is structural rather than a tuning choice.

Tool

Peak memory

What bounded it

pg_dump to psql

15 MiB median, under 40 MiB in every repetition

One COPY stream through a pipe, nothing buffered

Sling v1.5.20

103 MiB

One free CLI process per table, direct insert, no chunking

PeerDB stack

1.20 GiB across 7 containers

750,000 row snapshot partitions, two tables at a time

The baseline is a plain text dump fed straight into psql. Per the pg_dump docs, script output goes to standard output when no file is given, and the parallel -j option works only with the directory format. A piped dump is single stream by design, which is why it needs no memory and takes four times as long as the fastest tool.

Sling's run used SLING_DIRECT_INSERT so each table landed without a temp table, per the variables reference. The harness started one process per table because parallel streams and chunking need a CLI Pro token. The free path is the lightest footprint among the seven tools and the third slowest wall time.

PeerDB bounds memory at the partition. Its architecture page describes "a Flow API and horizontally scalable Flow Workers" on Temporal and a Postgres catalog. The mirror docs expose rows per partition and workers per table as the knobs, so its cost is CPU time and operational surface, not memory.

What this means when you size a replication host

Pick the tool by the host you can give it, then check the wall time you get in return. The main table carries both numbers, and the tiers below show how many of the eight runs fit under common memory limits.

Host memory budget

Runs that fit

Largest that fits

Under 128 MiB

2 of 8

Sling at 103 MiB

Under 2 GiB

3 of 8

PeerDB stack at 1.20 GiB

Under 8 GiB

5 of 8

ingestr at 4.83 GiB

Under 16 GiB

7 of 8

Debezium at 15.70 GiB

Under 64 GiB

8 of 8

dlt at 45.54 GiB

A container limit near 16 GiB fits every tool except dlt at these settings, but Airbyte's source and Debezium both sat within a fifth of that line. The low memory paths pay in time, since Sling is the third slowest run. Memory and CPU are separate bills, and PeerDB shows a small footprint can still cost thousands of CPU seconds.

The dataset has edges. It measures full loads on one table shape. The limits page says it "does not currently measure incremental catch-up, steady-state CDC throughput, or recovery after failure", so a week of CDC streaming is a number these files cannot give you.

Related guides

Frequently asked questions

How much memory does a database replication tool use?

It depends on the tool far more than on the data. On the 298 million row Postgres full load in this article, measured peaks ranged from a few megabytes for a pg_dump pipe to 45.5 GiB for dlt, with most tools landing in the low gigabytes. The architecture decides it, so check a measured figure for your tool and route before sizing a host.

Why does dlt use so much memory on a full load?

dlt extracts to disk in stages and keeps in-memory buffers in both the extract and normalize steps, and its normalize stage runs a pool of worker processes. The measured run used a pool of sixteen normalize workers plus as many load threads, each with a 200,000 item buffer, so the container held the main process and every worker's buffers at once.

How much memory does Debezium need for an initial snapshot?

In the measured run Debezium Server peaked at 15.7 GiB while snapshotting the full table set with eight snapshot threads, a bounded queue, and a 64 GiB JVM heap. The heap cap sets the ceiling, and the queue and batch settings decide how much of it fills, so smaller settings give a smaller figure and usually a longer run.

How much memory do Airbyte connectors use?

Airbyte runs the source and destination as separate containers. On this load the Postgres source container peaked at 12.8 GiB, roughly eight times the destination, under a 16 GiB limit per container. Airbyte's own docs say memory is the most common constraint because the orchestrator buffers records between source and destination.

Does more memory make a replication tool faster?

No. The two largest footprints after dlt, Debezium and Airbyte, were also the two slowest runs, while the 103 MiB Sling run finished faster than both. Throughput follows parallel reads and bulk writes, not buffer size. Memory tells you what host the tool needs, and wall time tells you how long the copy takes.

How was peak memory measured in this benchmark?

The harness samples every Docker container every 100 milliseconds through the Docker stats API and keeps the highest memory sample per container. The figures here sum those peaks for the median repetition. Because container peaks can happen at different moments, a summed stack figure is an upper bound rather than one instant.

How do you limit the memory a replication tool uses?

Each tool exposes a different knob. dlt uses buffer_max_items and file rotation. Debezium uses max.queue.size.in.bytes and the JVM heap. Airbyte uses a per-connector memory limit, PeerDB uses rows per snapshot partition, and ingestr uses page size and batch size. Lower values trade memory for more round trips and usually a longer run.

Why does PeerDB show seven containers in the results?

PeerDB ships as a Docker Compose stack. The measured run included the flow worker, the flow API, a snapshot worker, the PeerDB server, a Postgres catalog, Temporal, and the Temporal CLI. The flow worker held most of the memory and nearly all of the CPU, and the stack stayed under 1.3 GiB.

Is pg_dump to psql a fair baseline for replication tools?

It is a floor, not a competitor. A plain text pg_dump piped into psql streams one COPY at a time, which is why it never passed 40 MiB, but it is single stream, same engine only, and cannot resume. It shows what the copy costs with no tool in the way, which makes every tool's overhead visible.

Does this benchmark cover CDC or incremental memory usage?

No. The 2026-08-31 cohort measures full loads only, and its limits page says it does not measure incremental catch-up, steady-state CDC throughput, or recovery after failure. The Debezium figure is its initial snapshot, not streaming. Memory during a long CDC stream is a question these files do not answer.

More articles

Stay up to date with what weโ€™re building

Stay up to date with what weโ€™re building

Stay up to date with what weโ€™re building

Questions

Answered

FAQ

What does Galaxy do?

What is Filament?

What is enterprise context management?

What does working with Galaxy look like?

How do you handle security and compliance?

Why does Galaxy build in the open?

Own your knowledge stack

Own your knowledge stack

Copyright ยฉ 2026 Galaxy. All rights reserved.