A Preview of DuckDB v2.0
A Sneak Peek at DuckDB v2.0
By Mark Raasveldt and Hannes Mühleisen
Published: 2026-08-17 | Reading Time: ~15 min
TL;DR: DuckDB v2.0 is scheduled for release this autumn.
This article provides a preview of the most significant updates arriving in v2.0, including the transition to a server-based model, the introduction of triggers, the elevation of the VARIANT type, asynchronous I/O, a revamped SQL parser, a fresh storage format, and various other enhancements.
🦆 Introducing "Cyanoptera"
DuckDB v2.0 is codenamed “Cyanoptera,” named after the Anas cyanoptera (the cinnamon teal), a duck known for its distinct reddish-brown plumage in the western Americas.
![]()
Moving to a major version is a significant decision. This isn't just a symbolic update; v2.0 introduces:
- A brand new SQL parser.
- A new default format for storage.
- A completely overhauled C API.
- A curated set of breaking changes.
This release is the culmination of over commits since the launch of v1.5 in March. While the previous year focused on the "lakehouse" concept, this version marks the beginning of the Year of DuckDB as a Server.
🌐 DuckDB as a Server: Quack and CONNECT
Historically, DuckDB has been strictly an in-process database. However, due to overwhelming demand, the team has introduced a client/server architecture.
The Quack Protocol
The quack extension provides the native communication protocol. Now graduating to stable in v2.0, it allows any DuckDB instance to act as a server, while other DuckDB instances can attach to it via the new CONNECT statement.
Example Workflow:
-- On the Server
CALL quack_serve ( token = 'my_token' );
-- On the Client
ATTACH 'quack:server.example.com' AS qk ( TOKEN 'my_token' );
CONNECT qk ;
SELECT count ( * ) FROM events ; -- Processed on server, results streamed back
DISCONNECT ;
Beyond Quack: Remote Pushdown
The CONNECT statement is versatile. It isn't limited to DuckDB-to-DuckDB communication. Thanks to the new remote pushdown optimizer (see PR #22914), DuckDB can now send SQL directly to PostgreSQL or MySQL, avoiding the need to pull entire tables across the network.
CONNECT 'postgres://localhost/mydb' ;
SELECT count ( * ) FROM orders ; -- Execution happens on the Postgres server
DISCONNECT ;
Transactional Power and Observability
Contrary to assumptions about analytical engines, DuckDB was designed from the start as a transactional, multi-connection system featuring full MVCC (Multi-Version Concurrency Control) and transaction isolation. It is performant enough to rival PostgreSQL in several workloads.
To support long-term server deployments, v2.0 introduces enhanced observability:
- Improved Metrics: A reworked metrics layer (PR #22799).
- Better Logging: Enhanced visibility into instance activity.
Interestingly, the community responded to the Quack preview by building their own standalone clients, proving the demand for a decoupled architecture.
💎 VARIANT: The First-Class Citizen
Introduced in v1.5, the VARIANT type is essentially JSON on steroids. While it allows for the flexible, semi-structured data typical of JSON, it is not stored as text.
Instead, DuckDB employs a process called "shredding":
This allows for high compression and rapid query execution without requiring a predefined schema, making it ideal for evolving real-time log streams.
v2.0 Enhancements for VARIANT:
- Storage Execution: Shredded execution directly from storage (PR #20912).
- Scan Optimization: Extraction pushdown into scans (PR #22478).
- Parquet Integration: Support for reading/writing shredded
VARIANTdata. - New Functions: A suite of
variant_*utilities.
Code Example:
CREATE TABLE events ( payload VARIANT );
INSERT INTO events VALUES ( '{"user": {"id": 42, "tags": ["a", "b"]}}' :: JSON :: VARIANT );
-- Inspecting the variant
SELECT variant_type ( payload ), variant_keys ( payload ) FROM events ;
-- Filtering using variant logic
SELECT * FROM events WHERE variant_contains ( payload , { 'user' : { 'id' : 42 }}:: VARIANT );
Future Outlook: The team intends to eventually back the standard JSON type with VARIANT, granting existing JSON users these performance gains automatically.
⚡ Triggers
DuckDB v2.0 finally implements a comprehensive trigger system. The feature set includes:
BEFOREandAFTERtiming.FOR EACH ROWandFOR EACH STATEMENTgranularity.- Transition tables using
REFERENCING OLD TABLEandNEW TABLE. - Support for multiple triggers per event.
RETURNINGclauses on triggered tables andDROP TRIGGERfunctionality.
Use Case: Audit Logging
The most common application is maintaining an audit trail of changes.
CREATE TABLE target ( id INTEGER, val INTEGER );
CREATE TABLE audit ( id INTEGER, old_val INTEGER, new_val INTEGER );
CREATE TRIGGER trg_audit
AFTER UPDATE ON target
REFERENCING OLD TABLE AS o NEW TABLE AS n
FOR EACH STATEMENT
INSERT INTO audit
SELECT n.id, o.val, n.val
FROM o JOIN n ON o.id = n.id ;
INSERT INTO target VALUES ( 1, 10 ), ( 2, 20 );
UPDATE target SET val = val * 10 WHERE id = 2 ;
Result of SELECT * FROM audit;
| id | old_val | new_val |
|---|---|---|
| 1 | 10 | 10 |
| 2 | 20 | 200 |
Triggers integrate naturally into the engine... (content ends here as per original snippet)