Skip to content

Introducing chdb Postgres extension: High-performance imports from cloud storage

image 512x512 1
Sep 8, 2026 · 11 minutes read

We're happy to announce a new Postgres extension: chdb. This extension expands Postgres import and export features via the chDB library, an in-process ClickHouse engine, providing efficient, flexible conversion to and from a wide array of data formats living on your favorite cloud storage systems.

Benchmark

And boy howdy do we mean efficient! We compared chdb's performance importing the NYC Taxi dataset (1m rows, wide table) in a number of data formats to three other Postgres extensions, all reading from a regionally-colocated AWS S3 bucket. To the chart!

In order to minimize differences and to optimize for measurement of extension performance rather than infrastructure, the chdb, pg_lake, and pg_duckdb benchmarks ran on r8id.xlarge ClickHouse Managed Postgres services with 4 vCPUs and 32 GB RAM; the aws_s3 benchmark ran on a db.r8g.xlarge AWS RDS host, also with 4 vCPUs and 32 GB RAM. Results average three runs for each import. See the benchmark source code for details.

Of the four extensions, chdb exhibits the most consistent performance. pg_duckdb and pg_lake, both backed by DuckDB, take around 2-3x as long to import data from CSV, JSON, and Parquet. Only aws_s3 approaches chdb's performance, but it supports a much more limited array of data formats.

Data formats

Did we mention data formats? The chdb extension can read and write a slew of data formats --- all those that ClickHouse itself supports. This table summarizes the supported data formats and compression algorithms of the extensions we compared; note that this chdb list of formats is but a subset of the formats it supports:

ExtensionCompressionData Formats
aws_s3noneText (TSV), CSV, Postgres Binary
pg_lakegzip, zstd, snappy (Parquet only)CSV, JSON, Parquet
pg_duckdbgzip, zstd, snappy (Parquet only)CSV, JSON, Parquet
chdbgzip, zstd, lz4, bz2, snappy, brotliTSV, CSV, JSON, BSON, Prometheus, Protobuf, Avro, Parquet, Arrow, XML, CapnProto, Markdown, MsgPack, ORC, and more!

As ClickHouse and the chDB library add more, the chdb extension will get them for free!

We benchmarked chdb performance loading the NYC Taxi dataset for a number of these formats, where it demonstrated quite consistent performance:

We used the JSONCompact format for compatibility with the other extensions. Other JSON formats, such as JSONCompactEachRow, will more closely approximate the performance of the other formats.

Usage

The chdb package ships with two extensions: a CREATE EXTENSION extension named chdb and a hook module named chdb_hook.

chdb extension

The chdb extension (docs) provides the chdb_query() function, which executes a single chDB query. For example, this query:

SELECT * FROM chdb_query($$
  SELECT * FROM s3('s3://datasets-documentation/my-test-bucket-768/some_prefix/some_file_1.csv');
$$) AS (id int, months int, days int);

Outputs:

id | months | days
----+--------+------
  1 |      2 |    3
  3 |      2 |    1
  4 |      5 |    6
(3 rows)

chdb_hook module

The chdb_hook module (docs) hooks into the COPY command to copy data to or from an AWS S3, Google Cloud Storage, Azure Blob Storage, file, or http URL. This example loads records from a CSV file on S3:

CREATE TABLE times (
    id     INT NOT NULL,
    months INT NOT NULL,
    days   INT NOT NULL
);

LOAD 'chdb_hook';
COPY times FROM 's3://datasets-documentation/my-test-bucket-768/some_prefix/some_file_1.csv';

After which the times table contains the records from the file:

# SELECT * FROM times;
 id | months | days
----+--------+------
  1 |      2 |    3
  3 |      2 |    1
  4 |      5 |    6
(3 rows)

A CREATE TABLE command may also derive its columns, and load its rows, from such a URL. Try this one (all the URLs in this piece point to legit data files):

CREATE TABLE reviews () WITH (
    copy_from = 's3://datasets-documentation/amazon_reviews/amazon_reviews_2015.snappy.parquet'
);

The resulting, fully-loaded table has this structure:

ColumnType
review_dateinteger
marketplacetext
customer_idnumeric(20,0)
review_idtext
product_idtext
product_parentnumeric(20,0)
product_titletext
product_categorytext
star_ratingsmallint
helpful_votesbigint
total_votesbigint
vineboolean
verified_purchaseboolean
review_headlinetext
review_bodytext

Data types

Like pg_clickhouse, chdb relies on the pg-clickhouse-c headers-only library to convert values from ClickHouse to Postgres, including its type mapping, as in the CREATE TABLE example above. The current release maps nearly all of the ClickHouse types to Postgres types and vice versa. These mappings work most of the time; when they don't, use the structure option to tell chdb what type to use.

For example, pg-clickhouse-c maps a Postgres JSON value to ClickHouse String, because ClickHouse JSON currently recognizes only JSON objects, while Postgres JSON supports objects, arrays, and JSON scalar values. But perhaps you're confident your JSON columns contain only objects, thanks to a check constraint:

CREATE TABLE projects (
    name   TEXT PRIMARY KEY,
    meta   JSON NOT NULL CHECK (json_typeof(meta) = 'object')
);

INSERT INTO projects
VALUES ( 'chdb',   '{"status": "release"}' ),
       ( 'walrus', '{"status": "revise"}'  );

To benefit from the increased flexibility and storage for object-aware storage formats such as Parquet JSON, use the structure option to map it to ClickHouse JSON:

COPY projects to 'file:///tmp/projects.parquet' (
    structure 'name String, meta JSON'
);

Cloud storage URLs

The chdb_hook extension reads and writes to all your favorite storage platforms. It determines the appropriate protocol from the URL scheme.

SchemesTarget
fileAbsolute path on the Postgres server
http, httpsHTTP URL
s3AWS S3
gs, gcs, ossGoogle Cloud Storage
az, azure, abfss, abfsAzure Blob Storage or Azure ABFS
hdfsHadoop Distributed File System

URLs may also use a number of wildcards to concurrently fetch multiple files. Revisiting the CREATE TABLE example above, this command finds and imports six files from S3:

CREATE TABLE times () WITH (
    copy_from = 's3://datasets-documentation/my-test-bucket-768/{some,another}_prefix/some_file_{1..3}.csv'
);

After which the times table contains the records from each file it loaded:

SELECT * FROM times;
 c1 | c2 | c3 
----+----+----
  1 |  2 |  3
  3 |  2 |  1
  4 |  5 |  6
  1 |  2 |  3
  3 |  2 |  1
  4 |  5 |  6
  1 |  2 |  3
  3 |  2 |  1
  4 |  5 |  6
  1 |  2 |  3
  3 |  2 |  1
  4 |  5 |  6
  1 |  2 |  3
  3 |  2 |  1
  4 |  5 |  6
  1 |  2 |  3
  3 |  2 |  1
  4 |  5 |  6
 (18 rows)

Architecture

Support for such a vast array of data formats and cloud platforms demands a panoply of dependencies. We avoid managing those dependencies by delegating the problem to the chDB library. But loading that library into a Postgres backend would be excessive, especially for typically occasional or periodic tasks such as loading from a data source once a day.

Data loading extensions thus take a variety of approaches to managing the size and complexity of such a library by a variety of means:

  • aws_s3 simply downloads files to the local file system and passes control to COPY; hence its limitation to AWS S3 sources and the formats that Postgres COPY supports
  • pg_duckdb embeds the DuckDB engine in the Postgres backend, overkill for occasional COPY needs
  • pg_lake runs a separate DuckDB-powered service and communicates with it via the libpq protocol, which permanently consumes resources on the Postgres host

The chdb extension adopts its own distinctive architecture: It embeds the chDB library into a separate helper application. Neither the extension nor chdb_hook link chDB. Instead, they start the helper app on demand and communicate with it via an efficient, in-memory channel: file descriptors (STDIN, STDOUT, and STDERR, plus another for configuration information).

This design prevents the chDB library from consuming any more resources than necessary to carry out a single command. It also isolates the PostgreSQL cluster itself from out of memory issues that using shared memory with a background worker would suffer.

When the helper app finishes executing a command and has passed all its results to the backend (in ClickHouse Native format, straight from the source), it simply cleans up and exits, leaving the server resources to the service that most matters: PostgreSQL.

+-------------+
                  |   helper    |
+----------+      |    app      |      +------+
| Postgres |      | +---------+ |      | chDB |
| Backend  |<---->| |  chDB   | |<---->| Data |
+----------+      | | Library | |      +------+
                  | +---------+ |
                  +-------------+

What's next?

We plan to continue making chdb better. Potential roadmap items include:

  • Complete type mapping. We're gradually filling in the gap between Postgres and ClickHouse data types, to the benefit of both chdb and pg_clickhouse.
  • Access control to object storage via credential chain. Currently credentials required to read and write object stores must be passed explicitly in each chdb call. We'd like to allow transparent, server-configured credentialing to work as well.
  • Support for COPY (query) TO
  • Support for a WHERE condition on COPY
  • Support for all of the existing COPY options
  • Support for the Iceberg format
  • Query files directly from storage

Give it a try

Find the chdb extension in all the usual places, including GitHub and PGXN. We also provide it as part of the broader pg_clickhouse package on ClickHouse Managed Postgres; ask your support contact to add chdb_hook to your default configuration, or just connect to a superuser account via psql or your favorite client, run CREATE EXTENSION chdb; or LOAD 'chdb_hook'; and get started!

Get started with ClickHouse Managed Postgres today

Interested in seeing how ClickHouse Managed Postgres works on your data? Get started with ClickHouse Cloud in minutes and receive $300 in free credits.

Sign up

Share this post

  • Y Combinator icon
  • X icon
  • Bluesky icon
  • Facebook icon
  • LinkedIn icon

Subscribe to our newsletter

Stay informed on feature releases, product roadmap, support, and cloud offerings!

Recent posts