# How to Configure io_uring for Asynchronous I/O in Turso on Linux

> Learn how to configure io_uring for asynchronous I/O in Turso on Linux. Enable the io_uring Cargo feature and select the "io_uring" VFS for peak performance.

- Repository: [Turso Database/turso](https://github.com/tursodatabase/turso)
- Tags: how-to-guide
- Published: 2026-06-22

---

**Enable the `io_uring` Cargo feature at compile time and select the `"io_uring"` VFS at runtime to replace Turso's default syscall backend with Linux's high-performance ring-based asynchronous I/O interface.**

Turso, the edge-optimized database from tursodatabase/turso, provides an optional **io_uring** backend that replaces the standard synchronous VFS with a high-performance, ring-based interface. This Linux-only implementation, centered on the `UringIO` type in [`core/io/io_uring.rs`](https://github.com/tursodatabase/turso/blob/main/core/io/io_uring.rs), reduces system-call overhead through batched submissions and zero-copy buffers. Configuring it requires both compile-time feature selection and runtime VFS activation.

## Prerequisites and Feature Gating

The io_uring backend is strictly **Linux-only** and gated behind the `io_uring` Cargo feature. In [`core/Cargo.toml`](https://github.com/tursodatabase/turso/blob/main/core/Cargo.toml), this feature pulls in the external `io-uring` crate and enables the `rustix/io_uring` implementation. The code is wrapped in conditional compilation: `#[cfg(all(target_os = "linux", feature = "io_uring", not(miri)))]`.

If the target platform is not Linux, the code is excluded entirely. Attempting to use the `"io_uring"` VFS on non-Linux platforms results in a runtime error: `"io_uring is only available on Linux targets"` (see [`sdk-kit/src/rsapi.rs`](https://github.com/tursodatabase/turso/blob/main/sdk-kit/src/rsapi.rs)).

## How the io_uring Backend Works

The architecture centers on the `UringIO` struct defined in [`core/io/io_uring.rs`](https://github.com/tursodatabase/turso/blob/main/core/io/io_uring.rs). When initialized via `UringIO::new()` (lines 95-134), it creates an `io_uring::IoUring` instance, registers a sparse buffer arena for fixed-buffer I/O, and probes kernel opcode support.

### Submission and Completion Flow

All file operations—`open_file`, `pread`, `pwrite`, `pwritev`, `sync`, and `truncate`—build io_uring submission queue entries (SQEs) and push them into a shared `RingState` via `submit_entry`. A single leader thread serializes the `submit_and_wait` syscall while draining completion queue entries (CQEs).

When a CQE arrives, the `user_data` key maps back to a `Completion` via `completion_from_key`, waking the associated future. Write-vectors (`pwritev`) requiring multiple kernel calls are automatically resubmitted, and the future is woken with `wake_user_data`.

### Performance Characteristics

The ring batches up to **512 entries** (`ENTRIES = 512`) and waits for up to **4 completions** (`MAX_WAIT = 4`) per syscall, significantly cutting `io_uring_enter` syscalls. Fixed-buffer registration allows the kernel to operate directly on pre-registered memory, eliminating extra copies for reads and writes.

## Enabling the io_uring Backend

Follow these steps to configure the backend:

1. **Compile with the feature flag.** Build Turso using `cargo build --features=io_uring` or add `io_uring = true` to your workspace profile. On non-Linux targets, this code is excluded automatically.

2. **Select the VFS at runtime.** Pass the string `"io_uring"` to the database builder. In [`core/lib.rs`](https://github.com/tursodatabase/turso/blob/main/core/lib.rs), the factory maps this string to `Arc::new(UringIO::new()?)`. The SDK exposes this as `builder.with_io("io_uring".to_string())`, while the CLI accepts `tursodb --vfs io_uring`.

3. **Verify initialization.** Check the debug logs for the message `Using IO backend 'io-uring'` emitted by `UringIO::new`. If this line does not appear, the system has fallen back to the default syscall VFS.

### Fallback Behavior

If the kernel lacks support for specific opcodes (e.g., `IORING_OP_FTRUNCATE`), Turso logs a warning and executes the operation via synchronous POSIX syscalls, ensuring correctness on older kernels.

## Code Examples

### Rust SDK Configuration

```rust
use turso_sdk_kit::DatabaseBuilder;

fn main() -> turso_sdk_kit::Result<()> {
    // Selects the io_uring VFS registered in core/lib.rs
    let db = DatabaseBuilder::new()
        .with_path("/var/lib/turso/my.db")
        .with_io("io_uring".to_string())
        .open()?;
    
    // All subsequent I/O uses the io_uring ring via UringIO
    let rows = db.query("SELECT * FROM users", ())?;
    Ok(())
}

```

### CLI Usage

```bash
tursodb \
    --path /var/lib/turso/my.db \
    --vfs io_uring \
    repl

```

### Integration Testing

```rust
// From tests/integration/query_processing/test_write_path.rs
let db = TestBuilder::new()
    .with_io_uring(true)
    .open();
db.execute("PRAGMA journal_mode=WAL").unwrap();
db.execute("INSERT INTO t (id) VALUES (1)").unwrap();
// Internally uses UringIO::pwritev for the write path

```

## Summary

- The io_uring backend is available **only on Linux** and requires the `io_uring` Cargo feature.
- The implementation lives in [`core/io/io_uring.rs`](https://github.com/tursodatabase/turso/blob/main/core/io/io_uring.rs) and registers the VFS name `"io_uring"` in [`core/lib.rs`](https://github.com/tursodatabase/turso/blob/main/core/lib.rs) and [`core/io/mod.rs`](https://github.com/tursodatabase/turso/blob/main/core/io/mod.rs) under `BUILTIN_VFS_NAMES`.
- Runtime selection uses `.with_io("io_uring")` in the SDK or `--vfs io_uring` in the CLI.
- The backend batches up to 512 submissions and uses fixed buffers to minimize syscall overhead, gracefully falling back to POSIX syscalls for unsupported kernel opcodes.

## Frequently Asked Questions

### Is io_uring available on macOS or Windows?

No. The io_uring backend is strictly Linux-only. Attempting to use `"io_uring"` on other platforms triggers a runtime error stating that "io_uring is only available on Linux targets" as implemented in [`sdk-kit/src/rsapi.rs`](https://github.com/tursodatabase/turso/blob/main/sdk-kit/src/rsapi.rs). Windows users should use the `experimental_win_iocp` VFS instead.

### What happens if my kernel does not support io_uring?

If the kernel lacks support for specific io_uring opcodes (detected via the `Probe` during `UringIO::new`), Turso logs a warning and falls back to synchronous POSIX syscalls for those operations. The database remains functional but without the performance benefits of the ring-based interface.

### How do I verify that Turso is actually using io_uring?

Check the debug logs for the message `Using IO backend 'io-uring'` emitted by `UringIO::new` in [`core/io/io_uring.rs`](https://github.com/tursodatabase/turso/blob/main/core/io/io_uring.rs). If this line does not appear, verify that you compiled with the `io_uring` feature and explicitly selected the `"io_uring"` VFS at runtime.

### Does io_uring improve performance for all workloads?

io_uring primarily benefits workloads with high concurrent I/O or large batch operations by reducing syscall overhead and enabling zero-copy transfers via fixed-buffer registration. Single-threaded, low-concurrency workloads may see minimal improvement, though the batching of submissions still reduces context switches.