Documentation sections

Work

Analytical databases Beta

Analytical databases are in Beta.

The CLI labels it "Analytical · DuckDB (Beta)"; the web app shows the same Beta badge next to the kind. Behavior can change before general availability.

An analytical database is a second kind of workspace database, built for tables loaded in batches by your workflows and syncs, and for GROUP BY/join queries over whole tables — read-only SQL, with a size cap that depends on your plan. It lives on the same Databases page as your existing databases, with the same create button, names, delete/undelete, and rename.

Last reviewed July 14, 2026

In the app Work → Databases → Create → Analytical · DuckDB

Which kind do I need?

KindEngineWhat it's for
StandardSQLite (libSQL)Live rows and app state — row-at-a-time reads and writes. See Workspace databases.
AnalyticalDuckDBTables loaded in batches by workflows and syncs; fast GROUP BY and joins over whole tables; history.

The kind is chosen once, at creation, and cannot change. Names are unique per workspace across both kinds.

solidactions database create warehouse --kind duckdb

The CLI's database create defaults to a standard database; pass --kind duckdb for analytical. Creating an analytical database takes about a minute — the CLI waits and polls database show until it's ready unless you pass --no-wait.

Loading data

An analytical database is written through one door: ingest. Every write is a batch into a table — a staged file (Parquet, CSV, or JSONL) or up to 5 MB of rows inline from a workflow step.append (the default) creates the table on first use, adds new columns automatically, and widens compatible types; replace makes the batch the whole table, for full-refresh syncs and marts.

solidactions database ingest warehouse events.parquet --table events
solidactions database ingest warehouse events.csv --table events --mode replace

Every batch is acked durable — the ack means the data is on durable storage and survives anything. An inline batch (the webhook shape) acks in about one to two seconds; a staged file acks when its load completes. Every batch carries a caller-chosen batch_id, so retries are safe: resending the same id with the same table, mode, ack level, format, and content returns the original outcome and applies nothing — restaging the same rows in a different format (say, .csv instead of.parquet) is a 409 batch_conflict instead. That holds for 90 days after the batch finished.

From a workflow, bind the database by name in solidactions.yaml and ingest through the SDK'screateAnalyticalDatabaseClient() (@solidactions/sdk ≥ 0.9.0):

env:
  - WAREHOUSE: {database: "warehouse"}
import {
  SolidActions,
  defineWorkflow,
  createAnalyticalDatabaseClient,
  type AnalyticalDatabaseBinding,
} from '@solidactions/sdk';

export const ingest = defineWorkflow<{ rows: Record<string, unknown>[] }, void>({
  name: 'analytical-ingest',
  async run(ctx) {
    const db = createAnalyticalDatabaseClient(ctx.vars.WAREHOUSE as AnalyticalDatabaseBinding);
    await SolidActions.runStep(() => db.append('events', ctx.input.rows), { name: 'append-events' });
    await SolidActions.runStep(() => db.ingestFile('events', './events.parquet'), { name: 'ingest-events-file' });
  },
});

append and replace take rows inline (up to 5 MB); ingestFile streams a.parquet, .csv, or .jsonl file through staged storage. Both derive a stable batchId the same way the CLI does, so wrapping the call in a durable step makes retries safe.

Reading data

Every read path is read-only by construction. In the app, use the Tables and Query dialogs. From the CLI:

solidactions database schema warehouse --json
solidactions database query warehouse \
  "select category, sum(amount) as total from events group by 1" --limit 1000

Ask your AI to query it directly through MCP — the same databases_query/databases_schematools work on both database kinds. From a workflow, the SDK's AnalyticalDatabaseClient is write-only — append, replace, and ingestFile — so a workflow step doesn't read the table back; use the CLI, MCP, or the app's Query dialog for that.database connect <name> prints the CLI query and ingest commands, the MCP line, and thesolidactions.yaml binding together:

solidactions database connect warehouse

Connecting directly from DuckDB or BI tools is coming later.

Read-only SQL

There is no SQL write path. An INSERT, UPDATE, or any DDL from any query surface fails immediately:

read-only: this is an analytical database — load data with `solidactions database ingest` or your workflow's ingest step

The SQLite-only CLI verbs — exec, dump, pull, push, andimport — are all refused on an analytical database, though not with the same message:exec prints the read-only text above, while dump, pull,push, and import print a shorter refusal pointing at database ingestand database query. Load data with database ingest (or your workflow's ingest step) instead.

Idle and waking

An analytical database sleeps after 10 seconds without a query or ingest, to save resources. Your data is always safe while idle, and no credits are used. The next query or ingest wakes it automatically — typically in under a second; a rare cold rebuild from durable storage takes longer, and the caller sees a short retry instead of a failure either way. To warm it up ahead of a heavy batch, wake it explicitly:

solidactions database wake warehouse

Size and the plan's size limit

Every analytical database shows its live size against its cap — 512 MB on Free, 1 GB on Pro and Scale (database show --json reports these as size_bytes and size_limit_bytes). The cap is hard: a batch is refused up front if it can't fit, and a batch that would push the database over the cap after loading is reverted before it's ever acked, so live size never exceeds the cap. Once at or over the cap, a replace load that fits or deleting data still works; append is refused until you free space.

Performance: many small loads and Optimize

Analytical databases store each load as a set of files. Many small loads — frequent syncs, webhook batches — create many small files, and scanning many small files is slower than scanning a few large ones. SolidActions consolidates files automatically in the background, so ordinary use never degrades. If scans feel slow right after heavy ingest, run Optimize to consolidate now. Optimize never changes your data; it only rewrites how it is stored. It usually takes seconds to a few minutes.

solidactions database optimize warehouse --wait

The platform also runs consolidation automatically on a schedule — most of the time you don't need to think about this at all.

Deleting and restoring

Delete moves the database to your Deleted list immediately; durable data is kept for the same retention window as standard databases. Undelete within that window rebuilds the database from durable storage. There is no point-in-time restore for analytical databases.

To reclaim space without deleting the whole database, drop one table:

solidactions database drop-table warehouse events --yes

Limits by plan

PlanAnalytical databasesSize cap
Free1 per organisation512 MB
Pro3 per organisation1 GB
Scale10 per organisation1 GB

Uses credits while awake, at the same rate as workflow runs. Idle databases don't use credits. The count is per organisation, across every workspace — not per workspace, since an analytical database is its own compute resource.

Next: connect a standard database directly with Workspace databases, or browse Reference for CLI, MCP, and SDK links — for the full verb list, run solidactions --help.