Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/nimdeveloper/better-duck/llms.txt

Use this file to discover all available pages before exploring further.

The Config struct is a fluent builder that lets you configure a DuckDB database before it is opened. Each method sets one DuckDB configuration key and returns Result<Config>, so you can chain calls and propagate errors with ?. A finished Config is passed to Connection::open_with_flags or Database::open_with_flags; if you don’t need custom settings, omit it entirely and use Connection::open or Connection::open_in_memory instead.

Creating a Config

Start from the default (no configuration keys set) and chain the builder methods you need:
use better_duck_core::config::Config;

let config = Config::default()
    .max_memory("1GB")?
    .threads(4)?;
Every builder method calls the underlying duckdb_set_config C API and returns Err(Error::DuckDBFailure(...)) if DuckDB rejects the value. Unknown keys also produce an error, so typos are caught at startup rather than silently ignored.

Config methods

access_mode
AccessMode
Sets the access mode of the database. Accepts one of three variants:
  • AccessMode::Automatic — DuckDB picks read-write or read-only based on whether the file is writable (default).
  • AccessMode::ReadOnly — Opens the file in read-only mode; writes will error.
  • AccessMode::ReadWrite — Forces read-write mode; errors if the file is not writable.
use better_duck_core::config::{AccessMode, Config};

let config = Config::default().access_mode(AccessMode::ReadOnly)?;
default_order
DefaultOrder
Sets the default sort order used when an ORDER BY clause specifies no direction.
  • DefaultOrder::Asc — ascending order (default).
  • DefaultOrder::Desc — descending order.
use better_duck_core::config::{Config, DefaultOrder};

let config = Config::default().default_order(DefaultOrder::Desc)?;
default_null_order
DefaultNullOrder
Controls where NULL values appear in sorted results when no NULLS FIRST / NULLS LAST clause is given.
  • DefaultNullOrder::NullsFirst — nulls sort before all non-null values (default).
  • DefaultNullOrder::NullsLast — nulls sort after all non-null values.
use better_duck_core::config::{Config, DefaultNullOrder};

let config = Config::default().default_null_order(DefaultNullOrder::NullsLast)?;
max_memory
&str
Sets the maximum memory DuckDB may use for query execution, expressed as a string with a unit suffix — e.g. "1GB", "512MB", "256KB". DuckDB will spill to disk once this limit is reached.
let config = Config::default().max_memory("2GB")?;
threads
i64
Sets the total number of threads the DuckDB query engine may use. Defaults to the number of logical CPU cores. Set to 1 for fully single-threaded operation (useful in embedded or resource-constrained environments).
let config = Config::default().threads(4)?;
enable_external_access
bool
When true (the default), DuckDB allows queries that access the filesystem or network — COPY TO/FROM, CSV readers, JSON readers, Parquet readers, pandas replacement scans, and similar I/O extensions. Set to false to sandbox a database so it can only read data that has already been inserted through the API.
let config = Config::default().enable_external_access(false)?;
enable_object_cache
bool
When true, DuckDB caches file-format metadata such as Parquet footers in memory. This can significantly reduce latency when the same files are scanned repeatedly. Disabled by default.
let config = Config::default().enable_object_cache(true)?;
enable_autoload_extension
bool
When true, DuckDB automatically installs and loads known extensions (such as json or parquet) the first time a query that requires them is executed. Sets both autoinstall_known_extensions and autoload_known_extensions internally. Disabled by default; enable it when you want seamless extension use without calling LOAD or INSTALL manually.
let config = Config::default().enable_autoload_extension(true)?;
allow_unsigned_extensions
(no argument)
Allows DuckDB to load third-party extensions that have not been signed by DuckDB Labs. Takes no argument — calling the method unconditionally enables the flag.
let config = Config::default().allow_unsigned_extensions()?;
custom_user_agent
&str
Attaches arbitrary metadata to the DuckDB connection for diagnostic or telemetry purposes. The string is forwarded to DuckDB’s custom_user_agent configuration key and may appear in server-side logs when connecting to MotherDuck or other DuckDB-compatible services.
let config = Config::default().custom_user_agent("my-app/2.0")?;
with
(key: impl AsRef<str>, value: impl AsRef<str>)
Sets an arbitrary DuckDB configuration key-value pair. Use this to access DuckDB settings that do not have a dedicated builder method. DuckDB will return an error if the key is unknown or the value is invalid.
let config = Config::default().with("preserve_insertion_order", "false")?;

Using Config

The following example combines several options and opens an on-disk database with the resulting Config:
use better_duck_core::{connection::Connection, config::{AccessMode, Config}};

fn main() -> better_duck_core::error::Result<()> {
    let config = Config::default()
        .access_mode(AccessMode::ReadWrite)?
        .max_memory("1GB")?
        .threads(4)?
        .enable_external_access(true)?;

    let mut conn = Connection::open_with_flags("my_database.duckdb", config)?;

    conn.execute_batch("CREATE TABLE IF NOT EXISTS events (id INTEGER, label TEXT)")?;
    Ok(())
}
You can also pass a Config to Database::open_with_flags when you need multiple connections sharing the same database:
use better_duck_core::{database::Database, config::{Config, AccessMode}};

let config = Config::default()
    .access_mode(AccessMode::ReadWrite)?
    .threads(2)?;

let db = Database::open_with_flags("shared.duckdb", config)?;
let mut conn_a = db.connect()?;
let mut conn_b = db.connect()?;
Config implements Drop — the underlying duckdb_config handle is freed automatically when the Config goes out of scope after being consumed by open_with_flags. You do not need to call any teardown function manually.

Build docs developers (and LLMs) love