Search Shortcut cmd + k | ctrl + k

Secure remote secrets storage with OPAQUE PAKE authentication, email/password registration, MFA login, and automatic ducklake mounting

Maintainer(s): dforsber

Compatibility Matrix

This table covers all DuckDB releases that have not reached end-of-life, including LTS releases, and shows the 2 most recent patch releases of each. Older patch releases are not listed, but the extension may be available for them as well.

Platform 1.4.4 1.4.5 1.5.5 1.5.6 2.0.0
Linux AMD64
Linux ARM64
macOS AMD64
macOS ARM64
Windows AMD64
Windows ARM64
WebAssembly

Installing and Loading

INSTALL boilstream FROM community;
LOAD boilstream;

Example

-- Setup: Install and load boilstream extension
INSTALL httpfs; LOAD httpfs;
INSTALL boilstream FROM community;
LOAD boilstream;

-- Option 1: Login with email/password/MFA (establishes OPAQUE session)
--     NOTE: Remember to clean up your ~/.duckdb/history
PRAGMA boilstream_login('https://api.example.com/[email protected]', 'password', '123456');
┌────────────────────────┬─────────────────────┬────────────────────┐
│         status         │     expires_at      │ ducklakes_attached │
├────────────────────────┼─────────────────────┼────────────────────┤
│ Session token obtained │ 2025-11-21 10:30:00 │                  2 │
└────────────────────────┴─────────────────────┴────────────────────┘

-- Option 2: Authenticate with bootstrap token (from SSO/web UI)
PRAGMA boilstream_bootstrap_session('https://api.example.com/secrets:TOKEN');
┌────────────────────────┬─────────────────────┬────────────────────┐
│         status         │     expires_at      │ ducklakes_attached │
├────────────────────────┼─────────────────────┼────────────────────┤
│ Session token obtained │ 2025-11-21 10:30:00 │                  2 │
└────────────────────────┴─────────────────────┴────────────────────┘

-- List all available ducklakes
FROM boilstream_ducklakes();
┌──────────────┬──────────────┬─────────────────┐
│ catalog_id   │ catalog_name │   description   │
├──────────────┼──────────────┼─────────────────┤
│ 5a805647-... │ my_analytics │ Sales analytics │
└──────────────┴──────────────┴─────────────────┘

-- List all cached secrets with expiration
FROM boilstream_secrets();
┌─────────────────────┬──────────┬─────────────────────┐
│        name         │   type   │     expires_at      │
├─────────────────────┼──────────┼─────────────────────┤
│ my_analytics        │ ducklake │ 2026-11-19 20:00:00 │
│ my_analytics_s3     │ s3       │ 2026-11-19 20:00:00 │
│ my_analytics_pg     │ postgres │ 2026-11-19 20:00:00 │
└─────────────────────┴──────────┴─────────────────────┘

-- Create new ducklake
PRAGMA boilstream_create_ducklake('new_catalog', 'My new ducklake');

-- Query ducklake (automatically attached)
USE my_analytics;
SHOW TABLES;

-- Create persistent secret onto BoilStream server
CREATE PERSISTENT SECRET s3_minio IN boilstream (
    TYPE S3,
    KEY_ID 'minioadmin',
    SECRET 'minioadmin',
    REGION 'eu-west-1',
    ENDPOINT 'localhost:9000',
    USE_SSL false,
    URL_STYLE 'path',
    SCOPE 's3://ingestion-data/'
);

About boilstream

Boilstream extension provides enterprise-grade remote secrets storage for multi-tenant DuckDB deployments.

Features:

  • 🔐 OPAQUE PAKE Authentication - Password-less authentication (IETF RFC 9807)
  • 🔒 End-to-end Encryption - AES-256-GCM/ChaCha20-Poly1305 for secrets and responses
  • 🔑 Cryptographic Key Derivation - HKDF-SHA256 with domain separation
  • 🛡️ Defense in Depth - HMAC verification before AEAD decryption
  • 🎯 Session Protection - Lock-step sequence protocol prevents hijacking
  • 🗄️ Ducklake Support - Auto-attach multi-tenant data catalogs
  • 🌐 SSO Integration - Bootstrap token exchange for web environments

Security:

  • Facebook's audited OPAQUE implementation (Rust + C++ FFI)
  • Protects against MITM attacks even if TLS is compromised
  • One-time bootstrap tokens with anonymous authentication
  • Session resumption with encrypted refresh tokens
  • Comprehensive test vectors and security specification

API Functions:

  • PRAGMA boilstream_register_user(url_with_email, password) - Register new user with MFA (displays QR code)
  • PRAGMA boilstream_verify_mfa(totp_code) - Complete registration and get backup codes
  • PRAGMA boilstream_login(url_with_email, password, mfa_code) - Email/password/MFA login
  • PRAGMA boilstream_bootstrap_session(url_with_token) - Authenticate with bootstrap token
  • boilstream_ducklakes() - List available ducklakes
  • boilstream_secrets() - List cached secrets with expiration
  • boilstream_buckets() - List available storage buckets
  • PRAGMA boilstream_create_ducklake(name, description) - Create new ducklake
  • PRAGMA boilstream_help - Show all available commands

Requirements:

  • httpfs extension (auto-loaded)
  • postgres_scanner extension (auto-loaded)
  • ducklake extension (auto-loaded)
  • Compatible REST API server (see API specification)

For detailed documentation, security specification, and setup instructions, visit the extension repository.

Added Functions

function_name function_type description comment examples
boilstream_attach_ducklake pragma NULL NULL  
boilstream_auth_result table NULL NULL  
boilstream_bootstrap_session pragma NULL NULL  
boilstream_buckets table NULL NULL  
boilstream_create_ducklake pragma NULL NULL  
boilstream_ducklakes table NULL NULL  
boilstream_help pragma NULL NULL  
boilstream_login pragma NULL NULL  
boilstream_quack_authn scalar NULL NULL  
boilstream_quack_authz scalar NULL NULL  
boilstream_quack_debug_session_count scalar NULL NULL  
boilstream_register_user pragma NULL NULL  
boilstream_secrets table NULL NULL  
boilstream_verify_mfa pragma NULL NULL  
ducklake_add_data_files table NULL NULL  
ducklake_cleanup_old_files table NULL NULL  
ducklake_commit table NULL NULL  
ducklake_current_snapshot table NULL NULL  
ducklake_delete_orphaned_files table NULL NULL  
ducklake_expire_snapshots table NULL NULL  
ducklake_flush_inlined_data table NULL NULL  
ducklake_last_committed_snapshot table NULL NULL  
ducklake_list_files table NULL NULL  
ducklake_merge_adjacent_files table NULL NULL  
ducklake_options table NULL NULL  
ducklake_rewrite_data_files table NULL NULL  
ducklake_scan table NULL NULL  
ducklake_set_commit_message table NULL NULL  
ducklake_set_option table NULL NULL  
ducklake_settings table NULL NULL  
ducklake_snapshots table NULL NULL  
ducklake_table_changes table_macro NULL NULL  
ducklake_table_deletions table NULL NULL  
ducklake_table_info table NULL NULL  
ducklake_table_insertions table NULL NULL  
murmur3_32 scalar NULL NULL  
postgres_clear_cache table NULL NULL  
postgres_close_pinned_connection scalar NULL NULL  
postgres_configure_pool table NULL NULL  
postgres_execute table NULL NULL  
postgres_hstore_get scalar NULL NULL  
postgres_hstore_to_json scalar NULL NULL  
postgres_pin_connection scalar NULL NULL  
postgres_query table NULL NULL  
quack_active_connections table NULL NULL  
quack_cancel table NULL NULL  
quack_check_token scalar NULL NULL  
quack_clear_cache table NULL NULL  
quack_connection_id scalar NULL NULL  
quack_generate_keys table NULL NULL  
quack_identify table NULL NULL  
quack_nop_authorization scalar NULL NULL  
quack_query table NULL NULL  
quack_query_by_name table NULL NULL  
quack_serve table NULL NULL  
quack_server_list table NULL NULL  
quack_stop table NULL NULL  
quack_uri_parser scalar NULL NULL  
read_postgres_binary table NULL NULL  
scan_data_from_quack_client table NULL NULL  
whoami table_macro NULL NULL  

Overloaded Functions

This extension does not add any function overloads.

Added Types

This extension does not add any types.

Added Settings

name description input_type scope aliases typed_value
boilstream_grammar_auto_activate Activate the boilstream SQL syntax (BOILSTREAM …, CREATE/ATTACH DUCKLAKE) on every new connection BOOLEAN GLOBAL [] true
default_secret_storage Allows switching the default storage for secrets. VARCHAR GLOBAL [] boilstream
ducklake_default_data_inlining_row_limit Default row limit for data inlining (0 disables inlining) UBIGINT GLOBAL [] 10
ducklake_default_version Default DuckLake version for new catalogs VARCHAR GLOBAL [] NULL
ducklake_max_retry_count The maximum amount of retry attempts for a ducklake transaction UBIGINT GLOBAL [] 10
ducklake_retry_backoff Backoff factor for exponentially increasing retry wait time DOUBLE GLOBAL [] 1.5
ducklake_retry_wait_ms Time between retries UBIGINT GLOBAL [] 100
ducklake_target_file_size Target file size for insertion and compaction VARCHAR GLOBAL [] NULL
ducklake_write_deletion_vectors [EXPERIMENTAL] Write Iceberg V3 deletion vectors (puffin) instead of positional delete files (parquet) BOOLEAN GLOBAL [] false
pg_array_as_varchar Read Postgres arrays as varchar - enables reading mixed dimensional arrays BOOLEAN GLOBAL [] false
pg_connection_cache Whether or not to use the connection pooling. This option is deprecated, instead to disable the connection pooling use "SET pg_pool_max_connections=0" for newly attached Postgres databases and "FROM postgres_configure_pool(catalog_name='my_attached_postgres_db', max_connections=0)" for already attached Postgres databases. BOOLEAN GLOBAL [] true
pg_connection_limit The maximum amount of concurrent Postgres connections. This option is deprecated, instead use "SET pg_pool_max_connections = 42" for newly attached Postgres databases and "FROM postgres_configure_pool(catalog_name='my_attached_postgres_db', max_connections=42)" for already attached Postgres databases. UBIGINT GLOBAL [] 6
pg_debug_show_queries DEBUG SETTING: print all queries sent to Postgres to stdout BOOLEAN GLOBAL [] false
pg_enable_filter_pushdown Whether or not to use filter pushdown BOOLEAN GLOBAL [] true
pg_idle_in_transaction_timeout_millis Postgres idle in transaction timeout in milliseconds to set on scan connections UINTEGER GLOBAL [] NULL
pg_null_byte_replacement When writing NULL bytes to Postgres, replace them with the given character VARCHAR GLOBAL [] NULL
pg_numeric_as_varchar Read Postgres numerics without precision and scale or precision > 38 as varchar instead of double BOOLEAN GLOBAL [] false
pg_numeric_nan_as_null Read Postgres numeric NaN value as NULL instead of throwing an error BOOLEAN GLOBAL [] true
pg_oauth_token OAuth bearer token for PostgreSQL OAUTHBEARER authentication. Takes priority over the PGOAUTHTOKEN environment variable VARCHAR GLOBAL [] NULL
pg_pages_per_task The amount of pages per task UBIGINT GLOBAL [] 1000
pg_pool_acquire_mode How to acquire connections from the pool: 'force' (always connect, ignore pool limit), 'wait' (block until available), 'try' (fail immediately if unavailable) (default: force) VARCHAR GLOBAL [] force
pg_pool_enable_reaper_thread Whether to enable the connection pool reaper thread, that periodically scans the pool to check the 'max_lifetime_millis' and 'idle_timeout_millis' and closes the connection which exceed the specified values. Either 'max_lifetime_millis' or 'idle_timeout_millis' must be set to a non-zero value for this option to be effective. This option only applies to newly attached Postgres databases, to configure a database that is already attached use "FROM postgres_configure_pool(catalog_name='my_attached_postgres_db', enable_reaper_thread=TRUE)" BOOLEAN GLOBAL [] true
pg_pool_enable_thread_local_cache Whether to enable the connection caching in thread-local cache. Such connections are getting pinned to the threads and are not made available to other threads, while still taking the place in the pool. This option only applies to newly attached Postgres databases, to configure a database that is already attached use "FROM postgres_configure_pool(catalog_name='my_attached_postgres_db', enable_thread_local_cache=FALSE)" BOOLEAN GLOBAL [] false
pg_pool_health_check_query The query that is used to check that the connection is healthy. Setting this option to an empty string disables the health check. This option only applies to newly attached Postgres databases, to configure a database that is already attached use "FROM postgres_configure_pool(catalog_name='my_attached_postgres_db', health_check_query=SELECT 42)" VARCHAR GLOBAL [] SELECT 1
pg_pool_idle_timeout_millis Maximum number of milliseconds the connection can be kept idle in the pool. This number is checked when the connection is taken from the pool. When the connection pool reaper thread is enabled ('pg_pool_enable_reaper_thread' option), then this number is checked in background periodically. This option only applies to newly attached Postgres databases, to configure a database that is already attached use "FROM postgres_configure_pool(catalog_name='my_attached_postgres_db', idle_timeout_millis=300000)" UBIGINT GLOBAL [] 60000
pg_pool_max_connections Maximum number of connections that are allowed to be cached in a connection pool for each attached Postgres database. This number can be temporary exceeded when parallel scans are used. This option only applies to newly attached Postgres databases, to configure a database that is already attached use "FROM postgres_configure_pool(catalog_name='my_attached_postgres_db', max_connections=42)" UBIGINT GLOBAL [] 6
pg_pool_max_lifetime_millis Maximum number of milliseconds the connection can be kept open. This number is checked when the connection is taken from the pool and returned to the pool. When the connection pool reaper thread is enabled ('pg_pool_enable_reaper_thread' option), then this number is checked in background periodically. This option only applies to newly attached Postgres databases, to configure a database that is already attached use "FROM postgres_configure_pool(catalog_name='my_attached_postgres_db', max_lifetime_millis=600000)" UBIGINT GLOBAL [] 0
pg_pool_wait_timeout_millis Maximum number of milliseconds to wait when acquiring a connection from a pool where all available connections are already taken. This option only applies to newly attached Postgres databases, to configure a database that is already attached use "FROM postgres_configure_pool(catalog_name='my_attached_postgres_db', wait_timeout_millis=60000)" UBIGINT GLOBAL [] 30000
pg_query_mode Query mode, one of: 'AUTO', 'COPY_BINARY', 'PLAIN_QUERY_BINARY', 'PLAIN_QUERY_TEXT' VARCHAR GLOBAL [] AUTO
pg_staleness_query Custom query used in place of the default table staleness query when pg_staleness_query_enabled resolves to true. Must contain a ${SCHEMA} placeholder and return at least 3 columns (identity, name, revision marker). Empty (default) uses the built-in pg_class/xmin query. VARCHAR GLOBAL [] NULL
pg_staleness_query_enabled Whether or not the table catalog cache checks Postgres for external DDL changes before serving a cache hit. Defaults to the opposite of pg_use_information_schema_introspection when not explicitly set (off for pg protocol compatible databases that may not support the underlying query, on for Postgres). BOOLEAN GLOBAL [] false
pg_statement_timeout_millis Postgres statement timeout in milliseconds to set on scan connections UINTEGER GLOBAL [] NULL
pg_use_binary_copy Whether or not to use BINARY copy to read data BOOLEAN GLOBAL [] true
pg_use_ctid_scan Whether or not to parallelize scanning using table ctids BOOLEAN GLOBAL [] true
pg_use_information_schema_introspection Use SQL-standard information_schema views for ATTACH-time schema discovery instead of pg_catalog.For compatibility with pg protocol compatible databases like spanner, cockroach, redshift, … BOOLEAN GLOBAL [] false
pg_use_text_protocol Whether or not to use TEXT protocol to read data. This is slower, but provides better compatibility with non-Postgres systems BOOLEAN GLOBAL [] false
quack_authentication_function Name of a callback function for authentication VARCHAR GLOBAL [] quack_check_token
quack_authorization_function Name of a callback function for authorization VARCHAR GLOBAL [] quack_nop_authorization
quack_cache_max_rows Maximum rows the server retains in the result cache (0 = unlimited) UBIGINT GLOBAL [] 100000
quack_debug_drop_batch DEBUG SETTING: do not send the SEND_DATA batch with this dense index (0 = off); the terminal message must then fail the statement instead of inserting less data UBIGINT GLOBAL [] 0
quack_debug_duplicate_sends DEBUG SETTING: send every SEND_DATA batch two times, imitating a transport retry; the receiver must drop the duplicate UBIGINT GLOBAL [] 0
quack_debug_emit_delay_ms DEBUG SETTING: max random delay in ms before the fetch collector publishes a batch, stressing out-of-order emission UBIGINT GLOBAL [] 0
quack_debug_fetch_delay_ms DEBUG SETTING: max random delay in ms before a FETCH response is published, stressing out-of-order batch arrival UBIGINT GLOBAL [] 0
quack_debug_send_delay_ms DEBUG SETTING: max random delay in ms before a SEND_DATA request goes out, stressing out-of-order batch arrival on the server UBIGINT GLOBAL [] 0
quack_default_client_id client_id used when ATTACH / quack_query omit one; precomputed at load from $QUACK_CLIENT_ID (empty opts out) or a random per-instance id. Set to '' to opt out. VARCHAR GLOBAL [] 199dcad3-36ef-4cc5-a680-479b517e3f57
quack_default_heartbeat_timeout Heartbeat lease timeout in seconds requested by clients when ATTACH / quack_query omit heartbeat_timeout UBIGINT GLOBAL [] 60
quack_enable_reconnects Enable reconnect support (clients acknowledge results, the server caches the last result until acknowledged) BOOLEAN GLOBAL [] false
quack_fetch_read_ahead FETCH requests kept in flight ahead of the scan (0 = number of async threads) UBIGINT GLOBAL [] 0
quack_loaded_at_us Epoch microseconds at extension load BIGINT GLOBAL [] 1793283594854879
quack_prepare_inline_rows Rows returned inline in the PREPARE response before the remainder is left to FETCH; drains whole batches, so it may overshoot to a batch boundary UBIGINT GLOBAL [] 24576
quack_rebalance_buffer_bytes Pending (unstamped) bytes the batch rebalancer buffers before gating non-minimum producers (0 = automatic, memory-manager governed) UBIGINT GLOBAL [] 0
quack_result_ttl Seconds an idle cached result is kept before it is dropped (0 = never) UBIGINT GLOBAL [] 3600
quack_server_keep_alive_timeout Seconds an idle keep-alive connection is kept open by the RPC server UBIGINT GLOBAL [] 300
quack_server_max_connections Maximum concurrent connections the RPC server accepts; beyond this new connections are refused UBIGINT GLOBAL [] 1024
quack_server_stream_buffer_bytes Server-side per-stream byte budget, at most a quarter of memory_limit: FETCH counts serialized payload bytes, INSERT counts decoded chunk allocations; 0 disables the limit UBIGINT GLOBAL [] 268435456
quack_target_batch_bytes Target in-memory size of one rebalanced batch (one wire message payload); batches are cut when they reach this size UBIGINT GLOBAL [] 33554432
temp_directory Set the directory to which temporary files are written. VARCHAR GLOBAL [] post.db.tmp
whoami_hostname Network hostname / public address VARCHAR GLOBAL []  
whoami_meta Provider-specific metadata as JSON VARCHAR GLOBAL [] {}
whoami_name Human-readable name for this node VARCHAR GLOBAL []  
whoami_provider Deployment provider (ec2, docker, local, …) VARCHAR GLOBAL []  
whoami_region Deployment region VARCHAR GLOBAL []  
whoami_started_at Node start time (ISO-8601 TIMESTAMP) VARCHAR GLOBAL []  
© 2026 DuckDB Foundation, Amsterdam NL
DuckDB Home Code of Conduct Trademark Use Blog