Introducing Read-Only Database Attach for SQLite in Turso

Glauber CostaGlauber Costa
Jamie BartonJamie Barton
Cover image for Introducing Read-Only Database Attach for SQLite in Turso

Turso 0.1.3 brings a powerful new capability: database attachment.

This feature allows you to connect multiple databases within a single session and query across them seamlessly, opening up new architectural patterns for your applications.

While SQLite has supported ATTACH DATABASE for years, it's limited to a default of 10 attached databases (maximum of 125). Turso removes this constraint, supporting an arbitrary number of attached databases. Currently, attached databases are read-only. We're working on full read-write support for future releases.

Until now, working with multiple databases in Turso meant managing separate connections and manually joining data in your application code. With ATTACH, you can now:

-- Attach a customer database in read-only mode
ATTACH DATABASE 'customers.db' AS customers;

-- Attach a products database in read-only mode
ATTACH DATABASE 'products.db' AS products;

-- Query across all three databases (main + attached)
SELECT
    c.name,
    c.email,
    p.product_name,
    o.order_date
FROM
    customers.users c
    JOIN main.orders o ON c.id = o.customer_id
    JOIN products.catalog p ON o.product_id = p.id
WHERE
    o.order_date > date('now', '-30 days');

Many applications need access to common reference data; country codes, currency information, product catalogs. Instead of duplicating this data, attach it read-only:

-- Every service can attach the shared reference database
ATTACH DATABASE '/shared/reference_data.db' AS ref;

-- Use reference data in queries
SELECT
    o.id,
    o.amount,
    ref.currencies.symbol,
    ref.countries.name as shipping_country
FROM orders o
JOIN ref.currencies ON o.currency_code = ref.currencies.code
JOIN ref.countries ON o.shipping_country_code = ref.countries.iso_code;

For applications dealing with historical data, you can keep archived data in separate databases and attach them on-demand:

-- Attach historical data for analysis
ATTACH DATABASE 'sales_2023.db' AS sales_2023;
ATTACH DATABASE 'sales_2024.db' AS sales_2024;

-- Run year-over-year comparison
SELECT
    strftime('%m', order_date) as month,
    SUM(CASE WHEN order_date LIKE '2023%' THEN amount END) as sales_2023,
    SUM(CASE WHEN order_date LIKE '2024%' THEN amount END) as sales_2024
FROM (
    SELECT order_date, amount FROM sales_2023.orders
    UNION ALL
    SELECT order_date, amount FROM sales_2024.orders
)
GROUP BY month;

In a microservices architecture, each service typically owns its database. Read-only attach lets you run cross-service queries without building complex data pipelines:

-- Attach databases from different services
ATTACH DATABASE 'auth.db' AS auth;
ATTACH DATABASE 'billing.db' AS billing;
ATTACH DATABASE 'inventory.db' AS inventory;

-- Run a business intelligence query across all services
SELECT
    auth.users.email,
    COUNT(billing.invoices.id) as total_invoices,
    SUM(billing.invoices.amount) as lifetime_value,
    COUNT(DISTINCT inventory.shipments.id) as total_shipments
FROM auth.users
LEFT JOIN billing.invoices ON auth.users.id = billing.invoices.user_id
LEFT JOIN inventory.shipments ON auth.users.id = inventory.shipments.user_id
GROUP BY auth.users.id;

As you can see, read-only attach makes it easy to run cross-service queries without building complex data pipelines.

#Current Implementation: Read-Only

In this initial release, attached databases are read-only. While full read-write support is planned for future versions, the current read-only implementation offers several advantages. It ensures data integrity by preventing accidental modifications during queries, enhances performance by eliminating the need for write locks or cross-database transaction coordination, and promotes simplicity through a clear separation between operational and analytical workloads. Additionally, it improves safety by allowing databases to be shared across multiple processes without the risk of corruption.

Unlike SQLite's built-in ATTACH which defaults to 10 databases (with a hard limit of 125), Turso supports attaching an arbitrary number of databases, making it ideal for complex multi-tenant architectures.

#Performance Improvements in 0.1.3

While read-only attach is the headline feature, this release includes critical performance improvements:

#WAL Checkpointing Fix

We fixed a write amplification bug where the entire WAL was being rewritten on every checkpoint. This fix dramatically reduces I/O for write-heavy workloads.

#B-Tree Free Space Reuse

The write path now properly reuses free space in B-Tree pages, eliminating another source of write amplification and reducing database growth.

#External Sort Support

Turso now supports external sorting for ORDER BY operations on datasets larger than available memory-crucial for analytics queries on attached databases.

#Connection Time Optimization

Database connection time has been significantly improved, especially for databases with many tables. This makes attaching multiple databases much faster. Learn how Turso made connections to SQLite Databases 575x faster.

#Try It Today

Read-only database attach is available in Turso 0.1.3:

# Rust
cargo add turso --version 0.1.3

# JavaScript/TypeScript
npm install @tursodatabase/turso@0.1.3

# Python
pip install turso==0.1.3

This feature opens up new architectural possibilities while maintaining SQLite's simplicity and performance.

We can't wait to see what you build with it!