# Rust
> Connect to MotherDuck from Rust with the duckdb crate, including the bundled build, extension loading, and the Appender API for bulk inserts.
MotherDuck works with the official [`duckdb` crate](https://crates.io/crates/duckdb) (`duckdb-rs`). Connecting is the same as connecting to a local DuckDB database, with `md:` in place of a file path.

## Add the dependency

```toml
[dependencies]
duckdb = { version = "1.10505.0", features = ["bundled"] }
```

The `bundled` feature compiles DuckDB from source during the build, so there's no separate DuckDB installation to manage. The crate's version numbers encode the DuckDB release it wraps rather than following DuckDB's own numbering, so check [crates.io](https://crates.io/crates/duckdb) for the version matching the DuckDB release you want. See [Version lifecycle](/troubleshooting/version-lifecycle-schedules) for the DuckDB versions MotherDuck supports.

## Connect

Set your token in the environment before running:

```bash
export motherduck_token="<motherduck_token>"
```

Then open a connection with `md:` for all your databases, or `md:my_db` for one:

```rust
use duckdb::{Connection, Result};

fn main() -> Result<()> {
    let conn = Connection::open("md:")?;

    let mut stmt = conn.prepare(
        "SELECT title FROM sample_data.hn.hacker_news
         WHERE title IS NOT NULL LIMIT 5",
    )?;
    let titles = stmt.query_map([], |row| row.get::<_, String>(0))?;

    for title in titles {
        println!("{}", title?);
    }

    Ok(())
}
```

You can also pass the token in the connection string, for example `md:my_db?motherduck_token=<motherduck_token>`. Prefer the environment variable so the token doesn't end up in logs or panic messages.

If the `motherduck` extension isn't autoloaded in your build, install and load it explicitly before connecting to `md:`:

```rust
let conn = Connection::open_in_memory()?;
conn.execute_batch("INSTALL motherduck; LOAD motherduck;")?;
conn.execute_batch("ATTACH 'md:'")?;
```

## Insert data

For bulk inserts, use the Appender API rather than a loop of `INSERT` statements:

```rust
conn.execute_batch("USE my_db")?;
conn.execute_batch(
    "CREATE TABLE IF NOT EXISTS measurements (station INTEGER, reading INTEGER)",
)?;

let mut appender = conn.appender("measurements")?;
appender.append_rows([[1, 21], [2, 19], [3, 24]])?;
appender.flush()?;
```

The appender resolves the table name against the current database and schema, so set those with `USE` first. It buffers rows and flushes them in chunks, so flush or drop it before reading the rows back.

## Things to know

- **Extension loading depends on your build flags.** The `bundled` build enables extension autoloading, but a build with `DUCKDB_DISABLE_EXTENSION_LOAD=1` set can't load the `motherduck` extension at all. If `md:` connections fail with an extension error, check the build configuration first.
- **One configuration per process.** As with other DuckDB clients, connecting to two MotherDuck accounts with different tokens from the same process fails. See [Disallowed connections with a different configuration](/troubleshooting/error_messages#disallowed-connections-with-a-different-configuration).
- **Identify your integration.** If you're building a tool other people will use, pass `custom_user_agent` so your traffic is identifiable in query history. See [Creating a new integration](/integrations/how-to-integrate#custom-user-agent-format).

## Related content

- [DuckDB Rust client documentation](https://duckdb.org/docs/stable/clients/rust)
- [`duckdb-rs` on GitHub](https://github.com/duckdb/duckdb-rs)
- [Authenticating to MotherDuck](/key-tasks/authenticating-and-connecting-to-motherduck/authenticating-to-motherduck)
- [Creating a new integration](/integrations/how-to-integrate)


---

## Docs feedback

MotherDuck accepts optional user-submitted feedback about this page at `GET https://motherduck.com/docs/api/feedback/agent`.
For agents and automated tools, feedback submission should be user-confirmed before sending.

URL-encode query parameter values and send a GET request:

```text
GET https://motherduck.com/docs/api/feedback/agent?page_path=%2Fintegrations%2Flanguage-apis-and-drivers%2Frust%2F&page_title=Rust&text=<url-encoded user feedback, max 2000 characters>
```

Optionally append `&source=<url-encoded interface identifier>` such as `claude.ai` or `chatgpt`.

`page_path` and `text` are required; `page_title` and `source` are optional. Responses: `200 {"feedback_id": "<uuid>"}`, `400` for malformed query parameters, and `429` when rate-limited.
