
DuckDB v1.4 shipped November 19 with built-in AES-256-GCM encryption. PostgreSQL’s encryption options are minimal, and SQLite charges $2,000 for theirs. DuckDB encrypts database files transparently with two lines of code and 5-10% performance overhead. If you’re using DuckDB for analytics or multi-tenant SaaS, encryption just became trivial.
Why DuckDB Encryption Matters
Embedded databases have struggled with encryption. PostgreSQL offers filesystem-level encryption at best. PostgreSQL’s encryption options are limited. SQLite’s official encryption is a $2,000 add-on. Free alternatives exist—SqliteMultipleCiphers, SQLCipher—but they’re third-party with varying quality.
DuckDB is now the first major embedded analytical database with free, performant, built-in encryption. For a project with 30,000+ GitHub stars and growing enterprise adoption, this was the missing piece. Compliance frameworks like SOC 2 require encryption at rest. Multi-tenant SaaS platforms need per-customer encryption keys. DuckDB v1.4 delivers all of this, open-source, with minimal overhead.
What DuckDB Encryption Does
DuckDB uses AES-256-GCM (Galois Counter Mode), an industry-standard authenticated encryption algorithm. Encryption happens at the block level (256KB blocks). Each block gets a unique 16-byte nonce and 16-byte authentication tag. The main database header stays plaintext. Everything else gets encrypted: data, indexes, metadata, the Write-Ahead-Log (WAL), and temporary spill files.
You provide a key. DuckDB derives a secure key using a Key Derivation Function (KDF) with a random 16-byte salt. The derived key lives in secure memory that’s never swapped to disk. DuckDB immediately wipes the original input key from memory.
Threat model: Encryption protects against file theft, unauthorized storage access, and VM compromise. It does not protect against memory dumps or inspecting a running process.
How to Enable Encryption
Creating an encrypted database is straightforward:
ATTACH 'encrypted.db' AS enc (
ENCRYPTION_KEY 'your-secure-32-byte-key',
ENCRYPTION_CIPHER 'GCM'
);
CREATE TABLE enc.sales (
id INTEGER,
amount DECIMAL,
customer VARCHAR
);
INSERT INTO enc.sales VALUES (1, 99.99, 'Acme Corp');
Queries work transparently. No SQL changes. No special syntax.
In Python:
import duckdb
conn = duckdb.connect(
'encrypted.db',
config={'encryption_key': 'your-secure-key-here'}
)
conn.execute("""
CREATE TABLE users (id INTEGER, email VARCHAR)
""")
conn.execute("INSERT INTO users VALUES (1, 'alice@example.com')")
result = conn.execute("SELECT * FROM users").fetchall()
print(result)
conn.close()
Check encryption status:
FROM duckdb_databases();
This shows which databases are encrypted and which cipher they use.
Encrypting an Existing Database
Use COPY FROM DATABASE:
ATTACH 'old.db' AS old;
ATTACH 'encrypted.db' AS enc (ENCRYPTION_KEY 'secure-key');
COPY FROM DATABASE old TO enc;
Re-encrypting with a new key works identically. Key rotation is now a one-liner.
Performance: 5-10% Overhead
The DuckDB team benchmarked encryption using TPC-H queries at scale factor 1. Results: AES-256-GCM adds 5-10% overhead. AES-256-CTR adds 2-5%. The overhead is minimal because DuckDB leverages hardware-accelerated AES instructions (AES-NI on x86, ARMv8 on ARM). Block-level encryption means DuckDB only encrypts blocks it actually touches.
A Hacker News user who built a naive OpenSSL-based encryption wrapper reported 2x query runtime and high memory consumption. Switching to DuckDB v1.4’s block-level encryption: “practically no cost.”
When should you use CTR instead of GCM? Rarely. GCM adds authentication tags that verify data integrity. CTR skips this for slightly better performance. Use CTR only if you have other integrity checks and need every millisecond.
Real-World Use Cases
Compliance Requirements: SOC 2 audits require encryption at rest. GDPR and HIPAA mandate it for PII and PHI. Financial data processing often demands encryption. DuckDB v1.4 checks all boxes.
Multi-Tenant SaaS: A Hacker News commenter runs a Bayesian analytics platform where each customer has hundreds of datasets with separate encryption keys. Organizational keys rotate daily. DuckDB’s per-database encryption makes this architecture feasible.
Encrypted CDN Distribution: Put an encrypted DuckDB file on a CDN. A fleet of instances attaches read-only using the decryption key. You’ve distributed private data globally with edge caching, all encrypted. This wasn’t possible with Parquet encryption.
Cloud Security: Cloud VM compromises happen. With encryption, storage access alone doesn’t leak data. Temporary files and WAL entries are also encrypted.
Why DuckDB’s Encryption Is Better
PostgreSQL has limited encryption options. Mostly filesystem-level (LUKS, dm-crypt), which doesn’t help with CDN distribution or per-customer keys. SQLite’s official encryption is a $2,000 add-on. Free alternatives vary in quality and support. DuckDB’s encryption is first-party, built-in, zero dependencies.
DuckDB bundles MbedTLS for encryption by default. No external dependencies. If you load the httpfs extension (which includes OpenSSL), DuckDB automatically switches to OpenSSL’s hardware-accelerated code. The user doesn’t configure this. It just works.
Key Takeaways
- DuckDB v1.4 ships free AES-256-GCM encryption with 5-10% performance overhead
- Two lines of code enable transparent encryption—no SQL changes required
- First major embedded analytical database with built-in, performant encryption
- Real-world use cases: SOC 2 compliance, multi-tenant SaaS, encrypted CDN distribution
- Hardware-accelerated (AES-NI, ARMv8) for minimal overhead vs naive whole-file encryption
Install DuckDB v1.4 or later. Read the official deep-dive for implementation details and benchmarks. After 15 years of embedded database encryption being either expensive or nonexistent, someone finally solved it right.











