Database field guide · 40
PostgreSQL Analytics Federation
DuckDB, foreign data, Parquet, and pushdown
Design and verify analytical queries that cross PostgreSQL, embedded DuckDB, foreign servers, and object-storage files without hiding data movement.
Franck Pachot7 chaptersPostgreSQL · DuckDB · FDW · Parquet · pushdown
Build the mental model before choosing the mechanism.
This minibook was AI-generated from Franck Pachot's archived blog posts. Links to the original articles are included for source context and verification.
01
Federation moves work or data
A query spanning engines can ship predicates and aggregates to the data, pull rows into the coordinator, or combine both. The SQL text alone does not reveal which boundary was crossed.
- Draw every engine and storage boundary.
- Count rows and bytes crossing each boundary.
- Treat network and object-store requests as plan work.
02
Embedded analytics changes the executor
An extension such as pg_duckdb can run analytical operators through DuckDB inside a PostgreSQL deployment while preserving a PostgreSQL entry point. That adds capability and also a versioned executable dependency.
- Confirm which operators run in each engine.
- Retain PostgreSQL, extension, and DuckDB versions.
- Include extension loading and restart requirements in operations.
03
Files need schemas and credentials
Parquet and Iceberg carry useful metadata, but access still depends on URI handling, credentials, network paths, type mapping, and catalog behavior. Managed services expose only an approved subset of those controls.
- Test representative nested and temporal types.
- Use least-privilege object access.
- Keep secrets outside SQL history and generated pages.
04
Pushdown is the decisive optimization
Filtering, projection, aggregation, ordering, and limiting near the source can avoid transferring irrelevant rows. Support is shape- and version-specific, so a remote-looking scan is not proof that useful work moved.
- Inspect both coordinator and remote plans.
- Compare source rows read with rows returned.
- Test unsupported expressions and parameterized predicates.
05
Federation does not create one transaction
A local statement can read several systems without giving them one MVCC snapshot, commit protocol, or failure boundary. Reproducible analytics must state the consistency point of every source.
- Record source snapshot or file version.
- Separate read consistency from query syntax.
- Define retry behavior for partial remote failures.
06
Compare complete data paths
Embedded DuckDB, a foreign data wrapper, a native managed-service extension, and extract-then-query pipelines optimize different constraints. Compare setup, pushdown, transfer, cache state, concurrency, and governance rather than one warm runtime.
- Use the same data and result invariant.
- Report planning and startup separately.
- Include upgrade, recovery, and observability costs.
07
Field manual
Concrete mechanics, diagnostic evidence, and executable patterns to carry into a real system.
01
Capture the execution boundary
Use each engine's plan output and retain the remote SQL or file scan details. A local Foreign Scan or Custom Scan node is only the start of the evidence.
EXPLAIN (ANALYZE, VERBOSE, BUFFERS, SETTINGS)
SELECT key, count(*)
FROM federated_source
WHERE event_time >= $1
GROUP BY key;
02
Measure pushdown by removing it
Compare equivalent queries with a pushdown-compatible predicate and a deliberately unsupported expression. Record source rows, transferred rows, bytes, requests, and elapsed time.
pushdown_ratio = rows_returned_by_source / rows_examined_at_source
transfer_ratio = rows_received_locally / rows_examined_at_source
# Keep plans and remote statements for both query shapes.
03
Inventory analytical extension state
Managed services may require allow-listing and a restart before CREATE EXTENSION. Capture the installed version and preload state rather than assuming another server has the same capability.
SELECT extname, extversion FROM pg_extension
WHERE extname IN ('pg_duckdb', 'postgres_fdw', 'oracle_fdw');
SHOW shared_preload_libraries;
SELECT name, setting, pending_restart FROM pg_settings
WHERE name = 'shared_preload_libraries';
04
Pin a reproducible file input
Object paths can be overwritten while a query remains syntactically identical. Record immutable object versions, file hashes, schemas, row counts, and the credentials scope used by the test.
input = {
'uri': 'object://bucket/path/data.parquet',
'version': '<immutable-version>',
'sha256': '<digest>',
'rows': '<count>',
'schema': '<captured-schema>'
}
08
Source articles
Optional deep dives with the complete experiments and product-version context behind this guide.