Skip to main content

DuckDB vs SQLite vs PostgreSQL

Learning Focus

Use this lesson to understand when to choose DuckDB over SQLite or PostgreSQL based on workload characteristics.

Overview​

All three databases support standard SQL, but they are designed for very different use cases.

FeatureDuckDBSQLitePostgreSQL
Storage ModelColumnarRow-basedRow-based
Primary UseAnalytics (OLAP)Embedded apps (OLTP)General-purpose (OLTP)
Server RequiredNoNoYes
ConcurrencySingle writer, many readersSingle writerFull multi-user
File Format.db (columnar).db (B-tree)Data directory
Parquet SupportNativeVia extensionVia Foreign Data Wrapper
Best ForAnalytical queriesSmall apps, mobileWeb apps, production OLTP

DuckDB Architecture​

Your App / Python / CLI
│
▼
DuckDB Engine (in-process)
│
┌────┴────────────────┐
│ Columnar Store │ ← .db file on disk
│ Vectorized Engine │ ← processes 1024 rows/batch
│ Parallel Executor │ ← uses all CPU cores
└─────────────────────┘

When to Use DuckDB​

Choose DuckDB when:

  • You are running analytical queries (GROUP BY, Window Functions, large JOIN)
  • Your data lives in Parquet, CSV, or JSON files
  • You want zero infrastructure overhead (no Docker, no server)
  • You need fast ad-hoc analysis inside a Python/R/Node.js script
  • You are building a data pipeline that queries S3 or HTTPFS sources

Avoid DuckDB when:

  • You need high-concurrency multi-user writes (use PostgreSQL)
  • You are building a mobile app with small transactional data (use SQLite)
  • You need row-level security and role-based access control (use PostgreSQL)

Side-by-Side Query Comparison​

Reading a 10M-row CSV file:

-- DuckDB (native, no import needed)
SELECT department, AVG(salary)
FROM read_csv_auto('employees.csv')
GROUP BY department;

-- SQLite (must import first)
.import employees.csv employees
SELECT department, AVG(salary) FROM employees GROUP BY department;

-- PostgreSQL (must use COPY or a loader)
COPY employees FROM '/path/employees.csv' CSV HEADER;
SELECT department, AVG(salary) FROM employees GROUP BY department;

DuckDB executes the file query directly without an import step.

Performance Benchmarks (Illustrative)​

Query TypeDuckDBSQLitePostgreSQL
Count 10M rows~0.1s~3s~1s
AVG on 10M rows~0.2s~5s~1.5s
GROUP BY 10M rows~0.3s~8s~2s
Single row lookup~5ms~1ms~2ms

DuckDB excels at scans; SQLite/PostgreSQL are faster for single-row point lookups.

Learning Check​

Questions:

  1. Which database would you use for a mobile iOS app? Why?
  2. You need to query a 500GB Parquet file on S3. Which database fits best?
  3. What makes DuckDB's vectorized engine faster than row-based engines for analytics?

Common Pitfalls​

PitfallConsequencePrevention
Using DuckDB as a web app backendPoor concurrent write performanceUse PostgreSQL for the web layer; DuckDB for analytics
Expecting SQLite-style tiny footprintDuckDB has a larger binaryBoth are acceptable for most local workloads
Mixing OLTP and OLAP in one systemPerformance degradationSeparate concerns: OLTP → Postgres, OLAP → DuckDB

Quick Reference​

-- DuckDB: Query a Parquet file
SELECT * FROM 'data.parquet' LIMIT 10;

-- DuckDB: Query a CSV without importing
SELECT COUNT(*) FROM read_csv_auto('data.csv');

-- DuckDB: Show database info
PRAGMA database_list;

What's Next​