> ## Documentation Index
> Fetch the complete documentation index at: https://better-duck.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Benchmarks

> How better-duck-core compares to the community duckdb crate across primitive types, composite types, and common operations — with methodology and the test system.

These benchmarks compare `better-duck-core` against the community
[`duckdb`](https://crates.io/crates/duckdb) crate across three groups: primitive types, composite
types, and common end-to-end operations. The honest summary: better-duck-core leads on **type
handling** (notably `UUID` and the temporal types) and offers a **safe composite-type appender** the
`duckdb` crate lacks, while the two are close on raw operation throughput.

## Methodology

<Note>
  **How the numbers were produced.** Latency columns are min / median / p95 over the measured reps
  (warmup discarded). Throughput is `item_count / median_latency`. Each library vendors its **own**
  copy of DuckDB and the two cannot be linked into one process, so each ran in its **own** process.
  The timings are still directly comparable — both are in-process, native calls with no
  subprocess-per-operation overhead on either side.
</Note>

The composite-type group is the one exception to a clean head-to-head; see the warning in that
section.

<AccordionGroup>
  <Accordion title="Test system">
    * CPU: Intel Core Ultra 7 155U (12 physical cores)
    * RAM: \~15.5 GB
    * Toolchain: `rustc 1.96.0` (the project [MSRV](/guide/versioning-and-compatibility))
    * Compared against the `duckdb` crate, each vendoring its own DuckDB build

    Absolute numbers depend on hardware; read the two crates **relative to each other** on the same
    machine, which is how they were measured.
  </Accordion>
</AccordionGroup>

## Primitive types

Insert + full-scan of 20,000 rows per type. better-duck-core is ahead on most primitive types, and
substantially faster on a few — notably `UUID` (≈50.95 ms vs ≈185.80 ms median), `TIMESTAMPTZ`
(≈50.47 ms vs ≈87.89 ms), and `TIMESTAMP` (≈47.30 ms vs ≈78.29 ms). The two are close on `HUGEINT`,
`UHUGEINT`, and `DECIMAL`.

<Frame caption="Primitive types — latency (lower is better)">
  <img src="https://mintcdn.com/better-duck/g81tPp3YdcoSdDnM/benchmarks/comparison-primitive-types-latency.svg?fit=max&auto=format&n=g81tPp3YdcoSdDnM&q=85&s=824a9fff3b68a8eac0d2eefba661363c" alt="Primitive types latency comparison" width="2280" height="620" data-path="benchmarks/comparison-primitive-types-latency.svg" />
</Frame>

<Frame caption="Primitive types — throughput (higher is better)">
  <img src="https://mintcdn.com/better-duck/g81tPp3YdcoSdDnM/benchmarks/comparison-primitive-types-throughput.svg?fit=max&auto=format&n=g81tPp3YdcoSdDnM&q=85&s=0fb5a077b5aa2afc875aaecd74e0dd3b" alt="Primitive types throughput comparison" width="2280" height="620" data-path="benchmarks/comparison-primitive-types-throughput.svg" />
</Frame>

## Composite types

Insert + full-scan of 2,000 rows of `LIST`, `ARRAY`, `STRUCT`, and `MAP`, using each library's
appender API.

<Warning>
  The `duckdb` crate has **no safe write API** for these composite types. In the charts, its row is a
  **neutral placeholder** (`better-duck-core`'s latency + 1 ms, throughput − 1) — **not** a
  measurement. Plotting the actual workaround (a vectorized bulk SQL insert) would be unfair, since
  that is a fundamentally different and much faster operation than a row-by-row appender. The real
  workaround timings are reported separately, for reference only, in the source report.
</Warning>

The takeaway is a **capability**, not a speed result: better-duck-core offers a safe
[appender](/core/appender) path for `LIST` / `ARRAY` / `STRUCT` / `MAP` where the `duckdb` crate
offers none. Treat the composite charts as "better-duck-core has this capability."

<Frame caption="Composite types — latency (duckdb crate is a placeholder, see warning above)">
  <img src="https://mintcdn.com/better-duck/g81tPp3YdcoSdDnM/benchmarks/comparison-composite-types-latency.svg?fit=max&auto=format&n=g81tPp3YdcoSdDnM&q=85&s=b2db14fa990d7e62466f4639c2e4f058" alt="Composite types latency comparison" width="900" height="620" data-path="benchmarks/comparison-composite-types-latency.svg" />
</Frame>

<Frame caption="Composite types — throughput (duckdb crate is a placeholder, see warning above)">
  <img src="https://mintcdn.com/better-duck/g81tPp3YdcoSdDnM/benchmarks/comparison-composite-types-throughput.svg?fit=max&auto=format&n=g81tPp3YdcoSdDnM&q=85&s=f438b95af74dc5bf6cffdc04c2a1dc5b" alt="Composite types throughput comparison" width="900" height="620" data-path="benchmarks/comparison-composite-types-throughput.svg" />
</Frame>

## Operations

A mix of end-to-end workloads. These results are mixed and reported faithfully: the `duckdb` crate is
somewhat faster on these particular operations, while better-duck-core stays competitive.

| Operation | What it measures | better-duck-core (median) | duckdb crate (median) |
| - | - | - | - |
| `crud_basics` | Single-row INSERT + point SELECT + UPDATE + DELETE | 9.26 ms | 6.89 ms |
| `bulk_ingest` | Ingest 10,000 rows via each library's appender | 49.01 ms | 43.74 ms |
| `analytical` | GROUP BY + AVG + ORDER BY on 100,000 rows (query only) | 4.94 ms | 4.36 ms |
| `prepared_reuse` | 100 point-SELECTs reusing one prepared statement | 140.28 ms | 108.20 ms |
| `all_types` | INSERT + full-scan of 1,000 rows across 11 column types | 53.43 ms | 43.51 ms |

<Frame caption="Operations — latency (lower is better)">
  <img src="https://mintcdn.com/better-duck/g81tPp3YdcoSdDnM/benchmarks/comparison-operations-latency.svg?fit=max&auto=format&n=g81tPp3YdcoSdDnM&q=85&s=fdf300b0532862d87acd7d63b47c6edb" alt="Operations latency comparison" width="900" height="620" data-path="benchmarks/comparison-operations-latency.svg" />
</Frame>

<Frame caption="Operations — throughput (higher is better)">
  <img src="https://mintcdn.com/better-duck/g81tPp3YdcoSdDnM/benchmarks/comparison-operations-throughput.svg?fit=max&auto=format&n=g81tPp3YdcoSdDnM&q=85&s=3ef70e2914305c1a91bda00f6be64c47" alt="Operations throughput comparison" width="900" height="620" data-path="benchmarks/comparison-operations-throughput.svg" />
</Frame>

## Reading the results

* **Type handling is better-duck-core's strength** — especially `UUID` and the temporal types, where
  it is multiples faster, and the safe composite-type appender the `duckdb` crate lacks entirely.
* **Raw operations are close**, with the `duckdb` crate marginally ahead on the simple CRUD /
  prepared-reuse paths measured here.
* Pick the crate that fits your workload *and* the API surface you want — the appender, columnar
  reads, UDFs, async/pooling, and Arrow/Polars interop are all part of better-duck-core's surface.

<CardGroup cols={2}>
  <Card title="Choosing an API" icon="signs-post" href="/guide/choosing-an-api">
    Match the crate and API surface to your task.
  </Card>

  <Card title="Core crate" icon="rust" href="/core/opening-connections">
    The driver API measured here.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.