DuckDB vs PostgreSQL
Both extensions share the same core functionality but have platform-specific features.
Feature Matrix
Section titled “Feature Matrix”| Feature | DuckDB | PostgreSQL |
|---|---|---|
| Core Type | ||
monetary type | Yes | Yes |
| Integer storage (no float errors) | Yes | Yes |
| 70+ currencies | Yes | Yes |
| Currency symbols parsing | Yes | Yes |
| Banker’s rounding | Yes | Yes |
| Operators | ||
| Arithmetic (+, -, *, /) | Yes | Yes |
| Comparison (=, <, >, etc.) | Yes | Yes |
| Currency mismatch errors | Yes | Yes |
| Aggregates | ||
| SUM | Yes | Yes |
| AVG | Yes | Yes |
| MIN/MAX | Yes | Yes |
| Country/Currency | ||
currency_for_country() | Yes | Yes |
countries_for_currency() | Yes | Yes |
| Exchange Rates | ||
| ECB rates | Yes | No |
| 10 exchange rate sources | Yes | No |
Arrow operator (->>) | Yes | No |
| Currency macros (USD, EUR) | Yes | No |
| Historical conversions | Yes | No |
| Installation | ||
| Community extension | Yes | Build from source |
| WASM support | Yes | No |
When to Use DuckDB
Section titled “When to Use DuckDB”- Analytics workloads: Columnar storage, vectorized execution
- WASM/browser: Interactive documentation, client-side analytics
- Exchange rates: Built-in functions for 10 sources
- Currency conversion: Arrow operator and macros for easy conversions
- Data pipelines: Read/write Parquet, CSV, JSON directly
When to Use PostgreSQL
Section titled “When to Use PostgreSQL”- Production OLTP: Mature, battle-tested for transactional workloads
- Existing PostgreSQL: Add monetary support to existing databases
- Full SQL compliance: Complete SQL standard support
- Ecosystem: Works with all PostgreSQL tools (pgAdmin, psql, etc.)
- Extensions: Combine with other PostgreSQL extensions
Code Compatibility
Section titled “Code Compatibility”Most code is portable between platforms:
Works on Both
Section titled “Works on Both”-- Type creationSELECT '100 EUR'::monetary;
-- ArithmeticSELECT '100 EUR'::monetary + '50 EUR'::monetary;SELECT '100 EUR'::monetary * 2;
-- ComparisonsSELECT '100 EUR'::monetary > '50 EUR'::monetary;
-- AccessorsSELECT monetary_amount('99.99 EUR'::monetary);SELECT monetary_currency('100 USD'::monetary);
-- Country/currency lookupSELECT currency_for_country('US');SELECT countries_for_currency('EUR');
-- AggregatesSELECT SUM(amount) FROM orders WHERE monetary_currency(amount) = 'EUR';DuckDB Only
Section titled “DuckDB Only”-- Exchange rate functionsSELECT * FROM ecb_exchange_rates();SELECT * FROM twelvedata_exchange_rates();
-- Currency conversionSET monetary_exchange_table = 'exchange_rates';SELECT '100 EUR'::monetary ->> 'USD';SELECT USD('100 EUR'::monetary);
-- Historical conversionSELECT USD_AT('100 EUR'::monetary, '2025-01-15');Migration Path
Section titled “Migration Path”PostgreSQL to DuckDB
Section titled “PostgreSQL to DuckDB”-- Export from PostgreSQLCOPY (SELECT * FROM transactions) TO '/tmp/transactions.csv' CSV HEADER;
-- Import to DuckDBCREATE TABLE transactions ASSELECT * FROM read_csv('/tmp/transactions.csv');DuckDB to PostgreSQL
Section titled “DuckDB to PostgreSQL”-- Export from DuckDBCOPY transactions TO '/tmp/transactions.csv' (HEADER);
-- Import to PostgreSQL\copy transactions FROM '/tmp/transactions.csv' CSV HEADERPerformance Characteristics
Section titled “Performance Characteristics”| Aspect | DuckDB | PostgreSQL |
|---|---|---|
| Bulk analytics | Excellent (columnar) | Good |
| Single-row OLTP | Moderate | Excellent |
| Concurrent writes | Limited | Excellent |
| Memory usage | Higher (columnar) | Lower |
| Startup time | Faster (embedded) | Slower (server) |
Shared Code Architecture
Section titled “Shared Code Architecture”Both extensions share C++ code in the shared/ directory:
monetary.hpp/cpp- CoreMonetarystructcurrency.hpp/cpp- Currency enum and metadatacountry.hpp/cpp- Country-to-currency mappingparser.hpp/cpp- String parsing logic
This ensures consistent behavior across both platforms.