/

Data Infrastructure

Postgres to Snowflake: The Complete Replication Guide

Intergalactic Data Labs

10 min read

Table of contents

Summarize

The best way to replicate Postgres to Snowflake in 2026 is logical replication CDC through pgoutput, run with Filament. It bootstraps each table from one exported snapshot, verifies every batch with a CRC32-C checksum, and resumes from checkpoints, all from one binary inside your own network. Fivetran, Airbyte, Estuary, and Openflow run the same route with a meter, a hosted model, or a NiFi cluster attached.

Tool

Route maturity

CDC method

Integrity

Deploy

Pricing unit

Filament

Source beta, sink alpha

pgoutput

CRC32-C per batch, checkpoints

Binary, Go library, Helm

None

Fivetran

GA, Postgres 10 to 18

pgoutput or xmin

Vendor managed

SaaS

Monthly active rows

Airbyte

Certified source, dest v5

pgoutput via Debezium or xmin

Raw plus final tables

OSS or Cloud

Per GB on Cloud

Estuary Flow

Supported, Postgres 10 plus

pgoutput plus watermarks

Transactional apply

SaaS, private, BYOC

Per GB plus per connector

Openflow (Snowflake)

Snowflake native, Postgres 11 plus

pgoutput, Snowpipe Streaming

Journal tables

Snowflake or BYOC

Snowflake credits

dlt

Library, pg_replication source

pgoutput

Load packages

Python

None, dltHub paid

Stitch

Released 2021, Singer tap

wal2json

Vendor managed

SaaS

Rows per month

PeerDB

Snowflake sink deprecated

pgoutput

Vendor managed

Docker stack

None

Maturity, CDC method, and license come from each tool's docs and LICENSE file. PeerDB still ranks for this route, but its README now calls the Snowflake destination "deprecated and no longer actively maintained."


How to replicate Postgres to Snowflake with Filament

Filament runs the route as one binary with a consistent snapshot bootstrap, sharded parallel reads, checkpointed resume, and per-batch integrity checks, staging Parquet straight into Snowflake. The setup is three commands once the Snowflake role exists, and the Postgres source is beta with the Snowflake sink at alpha today, per its docs.

Start on the Snowflake side. The sink docs ship the full SQL for a dedicated SERVICE user with key-pair auth, an X-Small warehouse with AUTO_SUSPEND = 60, the database, and the grants. Generate the key with openssl genrsa 2048 piped to pkcs8 -nocrypt.

Then define both ends and the pipeline. Connector fields become CLI flags with a source- or sink- prefix and underscores become hyphens, per the CLI reference. The docs' worked examples use Postgres and stdout sinks, so the Snowflake flags below follow that rule and the sink's config table. Confirm the auth flag names with filament sink create --help.

filament source create production \
  --source-connector postgres \
  --source-connection-method url \
  --source-dsn-env POSTGRES_DSN \
  --source-replication cdc

filament sink create warehouse \
  --sink-connector snowflake \
  --sink-account myorg-myaccount \
  --sink-username FILAMENT_USER \
  --sink-warehouse FILAMENT_WAREHOUSE \
  --sink-database-name FILAMENT_DATABASE \
  --sink-role FILAMENT_ROLE \
  --sink-auth-type key_pair \
  --sink-auth-private-key-env SNOWFLAKE_PRIVATE_KEY

filament pipeline create pg-to-snowflake \
  --source production --sink warehouse \
  --resources orders,customers \
  --write-mode

filament source create production \
  --source-connector postgres \
  --source-connection-method url \
  --source-dsn-env POSTGRES_DSN \
  --source-replication cdc

filament sink create warehouse \
  --sink-connector snowflake \
  --sink-account myorg-myaccount \
  --sink-username FILAMENT_USER \
  --sink-warehouse FILAMENT_WAREHOUSE \
  --sink-database-name FILAMENT_DATABASE \
  --sink-role FILAMENT_ROLE \
  --sink-auth-type key_pair \
  --sink-auth-private-key-env SNOWFLAKE_PRIVATE_KEY

filament pipeline create pg-to-snowflake \
  --source production --sink warehouse \
  --resources orders,customers \
  --write-mode

filament source create production \
  --source-connector postgres \
  --source-connection-method url \
  --source-dsn-env POSTGRES_DSN \
  --source-replication cdc

filament sink create warehouse \
  --sink-connector snowflake \
  --sink-account myorg-myaccount \
  --sink-username FILAMENT_USER \
  --sink-warehouse FILAMENT_WAREHOUSE \
  --sink-database-name FILAMENT_DATABASE \
  --sink-role FILAMENT_ROLE \
  --sink-auth-type key_pair \
  --sink-auth-private-key-env SNOWFLAKE_PRIVATE_KEY

filament pipeline create pg-to-snowflake \
  --source production --sink warehouse \
  --resources orders,customers \
  --write-mode

The first run creates the slot with an exported snapshot and reads each table in full through it, "so the baseline and the change stream share one consistent point," per the Postgres source docs. Large tables split into as many as 64 parallel ranges, saved in the checkpoint so a resumed run keeps its read plan. Filament creates the publication itself and keeps its table list current.

Each later run is a bounded catch-up to the current WAL position, so continuous CDC is a loop you schedule with cron or a Kubernetes job. On the write side, "each Arrow batch is encoded as a Snappy-compressed Parquet file in memory," uploaded with PUT to the user's stage, loaded with COPY INTO, and removed, per the sink docs. No bucket, storage integration, or Kafka sits in between.

Merge mode loads each batch into a temporary table and applies one MERGE, so the Snowflake table holds the current row per primary key rather than a raw event log. Before that write, the pipeline computes a CRC32-C checksum over the batch and the sink recomputes it at its boundary, per the integrity docs. Schema evolution is add-only into typed tables, and a failed attempt replays rather than skips.


How do Fivetran, Airbyte, Estuary, and Openflow run the same route?

All four use pgoutput logical replication, and each attaches something Filament does not need. That extra is a row meter, a raw table layer, a per-connector fee, or a NiFi cluster.

Fivetran has the widest managed Postgres range, 10 through 18, and recommends logical replication "if you have a large database," per its Postgres docs. Its query-based fallback uses xmin and "does not preserve details about deleted rows." Every synced row counts toward the monthly active rows meter, per its pricing page, so the bill grows with your tables.

Airbyte's certified Postgres source offers CDC through Debezium, xmin, or a user cursor, per its source docs. Its Snowflake destination writes each stream into a raw table plus a typed final table, per its docs. Cloud bills databases at $10 per GB, and the platform is ELv2 rather than Apache 2.0.

Estuary captures with pgoutput plus a watermarks table it writes into your database, and its Snowflake materialization supports Snowpipe Streaming, per the Estuary docs. It is priced per GB plus a fee per connector, per its pricing page, under BSL 1.1.

Openflow is Snowflake's replacement for its own native app connector, which Snowflake says is "not on our product roadmap" for general availability, per the connector docs. Openflow runs on Apache NiFi, loads through Snowpipe Streaming, and writes journal tables that "are retained indefinitely and are not automatically cleaned up," per the Openflow Postgres docs.


What does the Postgres side need?

Postgres needs wal_level = logical, a replication role, a publication, and a slot, and Filament manages the last two for you. The four settings are the same for every tool.

  • Set wal_level to logical, which "can only be set at server start," per the Postgres WAL config docs.

  • Give the connecting role the REPLICATION attribute, per the logical replication security docs.

  • Give every replicated table a primary key, since a table "must have a replica identity configured in order to be able to replicate UPDATE and DELETE operations," per the publication docs.

  • On RDS and Aurora, set rds.logical_replication to 1 and reboot the writer, per the Aurora docs.

The slot risk is disk. With the default max_slot_wal_keep_size of -1, "replication slots may retain an unlimited amount of WAL files," per the replication config docs. Filament advances its slot only after a committed write and refuses to run past a slot another client consumed, so the slot never silently diverges from what landed in Snowflake.


How do Postgres types land in Snowflake?

Most types map cleanly, but zoned timestamps differ by tool, so check the mapping before building dashboards on the copy.

Postgres

Filament

Openflow

Note

integer, bigint

NUMBER(38,0)

NUMBER

Same

numeric

NUMBER(p,s) up to 38

NUMBER

Snowflake's 38 digit ceiling

timestamp

TIMESTAMP_NTZ(6)

TIMESTAMP_NTZ

Wall clock, no zone

timestamptz

TIMESTAMP_TZ(6)

TIMESTAMP_LTZ

Fivetran and Airbyte use TZ

jsonb

VARIANT

VARIANT

Openflow caps values at 16 MB by default

uuid, array

TEXT

TEXT

Same in both

Mappings come from the Filament sink docs and the Openflow data mapping page. Snowflake's TIMESTAMP_TZ "only stores the offset of a given time zone, not the actual time zone," per the datetime docs, so Filament's choice keeps the offset your app wrote.

TOAST columns need one setting. Filament asks for REPLICA IDENTITY FULL on tables with large text or JSON values, while Openflow substitutes a placeholder your MERGE has to special-case.


Which tool fits which job?

No public benchmark covers this route, so speed is not a column here. On the one route with a public run, Postgres to Postgres, Filament moved 298M rows in 115 s and led every other tool, per the seven-tool benchmark. The same engine drives the Snowflake sink.

Tool

Best for

Trade-off

Cost

Filament

Verified, resumable CDC inside your network

Newest sink in its catalog

No meter, warehouse seconds only

Fivetran

Teams that will not run any software

MAR bill grows with rows, xmin drops deletes

MAR, 500k free

Airbyte

Broadest connector catalog

Raw plus final tables, ELv2

$10 per GB on Cloud

Estuary

Snowpipe Streaming delivery

BSL license, per-connector fee

$0.50 per GB plus $100 per connector

Openflow

Staying inside Snowflake

NiFi cluster, journal tables never auto-clean

Snowflake credits

dlt

Python pipelines as code

Build your own scheduling and checks

dltHub from $11,900 per month

Stitch

Simple row-based billing

Needs wal2json installed

From $100 per month

Debezium

Already running Kafka

Lands VARIANT, you write the MERGE

Kafka to run


Which Postgres to Snowflake tool should you pick?

Pick by the constraint that breaks first. If the constraint is correctness, Filament checksums every batch on both sides of the write and bootstraps CDC from a single consistent snapshot, per its docs. If it is control, Filament runs as one binary or a Go library inside your network, with no data leaving through a vendor.

If the constraint is cost at scale, every managed tool meters rows or gigabytes while Filament has no meter. The only bill is the Snowflake warehouse, "billed per-second, with a 60-second minimum," per the Snowflake cost docs. If it is latency, Filament's catch-up cycle runs as often as you schedule it.

The narrow cases go elsewhere. A team that will not run any software should look at Fivetran, and a shop already committed to NiFi inside Snowflake can use Openflow. Galaxy, which maintains Filament, publishes the connector maturity table and the benchmark harness in the open, so every claim above can be checked.

Related routes in this series cover Postgres to ClickHouse, the database replication guide, and the data movement tool roundup.


Frequently asked questions

What is the best way to replicate Postgres to Snowflake?

Run logical replication CDC through pgoutput with Filament. It bootstraps every table from one exported snapshot so the baseline and the change stream share a consistent point. It verifies each batch with a CRC32-C checksum, checkpoints so a failure resumes rather than restarts, and stages Parquet straight into Snowflake with no external bucket.

How does Filament write to Snowflake?

Each batch is encoded as a Snappy Parquet file in memory, uploaded with PUT to the user's internal stage, loaded with COPY INTO, and removed. Merge mode loads the batch into a temporary table and applies one MERGE, so the Snowflake table always holds the current row per primary key. No storage integration, bucket, or Kafka is needed.

Does Snowflake have a native Postgres connector?

Snowflake has three. The Snowflake Connector for PostgreSQL is a preview native app that Snowflake says will not reach general availability. Openflow Connector for PostgreSQL is its replacement, built on Apache NiFi and loading through Snowpipe Streaming. Snowflake Postgres data mirroring is a preview that only works when the source is a Snowflake Postgres instance.

What does Postgres need for CDC to Snowflake?

Set wal_level to logical, which needs a server restart, and give the replication user the REPLICATION attribute. Every replicated table needs a primary key so updates and deletes can be matched. On RDS and Aurora, set rds.logical_replication to 1 and reboot. Filament creates the publication and the replication slot itself and keeps the table list current.

Is Filament faster than Fivetran or Airbyte for Postgres to Snowflake?

No public benchmark covers this route yet, so no tool can claim it. On the one route with a public run, Postgres to Postgres, Filament moved 298 million rows in 115 seconds and finished ahead of every other tool measured. The same engine, sharded reads, and batch pipeline drive the Snowflake sink.

How much does Postgres to Snowflake replication cost?

Two bills apply. Fivetran meters monthly active rows, Airbyte Cloud and Estuary meter gigabytes, and Stitch meters rows, so the tool bill grows with your data. Filament runs on your own host with no meter. Snowflake then bills warehouse seconds for each COPY INTO and MERGE, so set the loading warehouse to auto suspend after 60 seconds.

How are Postgres types mapped to Snowflake?

Integers become NUMBER(38,0), numerics keep precision up to 38 digits, timestamps without zone become TIMESTAMP_NTZ, JSONB becomes VARIANT, and UUIDs become TEXT. Timestamps with zone differ by tool, since Filament and Fivetran use TIMESTAMP_TZ while Openflow uses TIMESTAMP_LTZ. Filament creates typed tables and adds new columns automatically.

Can I replicate from an Aurora or RDS read replica?

Not on Aurora, because Aurora does not offer logical decoding from read replicas, per AWS. Openflow requires Postgres 16 or newer for standby decoding and rules Aurora out for the same reason. Snowflake's native app connector must connect to the primary. Point every tool, Filament included, at the writer instance.

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.