> ## Documentation Index
> Fetch the complete documentation index at: https://developers.telnyx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SQL Databases

> Telnyx SQL Databases are standalone SQLite databases for Edge Compute, shared by every function that binds them. Query one from TypeScript through the env binding, or from anywhere over the REST query endpoint and the telnyx-edge CLI.

A SQL database is a SQLite database that lives on its own, outside any function. Create it once, bind it by id, and query it as `env.DB` from as many functions as need it — or from the CLI and REST API without deploying anything at all.

There is no server to size and nothing to deploy per database. Every path reaches the same data through one primary, so writes serialize and there is no replica lag to reason about.

## Two Ways to Reach a Database

The same database is reachable two ways. Pick based on where the code runs.

|                | `env` binding                                    | REST API and CLI                                                                                                                                     |
| -------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Where**      | Inside an edge function — TypeScript only        | Anywhere — any language, any host, no function required                                                                                              |
| **Auth**       | Injected by the runtime; no API key in your code | Your `TELNYX_API_KEY` as a bearer token                                                                                                              |
| **Shape**      | `env.DB.prepare(sql).bind(...).all()`            | `POST https://api.telnyx.com/v2/storage/sqldbs/{id}/actions/query`, `telnyx-edge storage sqldb execute`                                              |
| **Use it for** | Reads and writes on the request path             | Creating databases, applying schema and migrations, backfills, one-off inspection — SQL you wrote yourself, since this path has no parameter binding |

A row written by a function is visible to the next CLI query, and a table created from the CLI is visible to the next request. That is what lets schema exist before any code does: create the database, apply [migrations](/docs/edge-compute/sqldb/migrations), then ship a function that binds it.

## SQL Databases vs Per-Actor SQL

Stateful Actors also have SQLite, at [`ctx.storage.sql`](/docs/edge-compute/stateful-actors/guides/storage/sql). Both surfaces are SQLite, which is where the confusion starts. They solve different problems.

|                  | SQL Database (`env.DB`)                                                                                          | Actor SQL (`ctx.storage.sql`)                                                                     |
| ---------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| **Scope**        | One database, shared by the functions that bind its id                                                           | One private database per actor instance                                                           |
| **Reached from** | Any bound function, the CLI, the REST API                                                                        | Only from inside that one actor instance                                                          |
| **API shape**    | Async — `await env.DB.prepare(sql).bind(...).all()`                                                              | Synchronous — `ctx.storage.sql.exec(sql, ...)` returns a cursor                                   |
| **Use it for**   | Application data more than one caller reads: catalogs, links, accounts, anything an operator also needs to query | State owned by a single entity — a room, a session, a device — where the actor itself is the lock |

A per-actor database cannot be queried from outside its actor and cannot join across instances; there is no CLI or REST path to it. A SQL database can be queried from anywhere, but no caller gets exclusive access to it — concurrent callers interleave, and correctness across statements comes from `batch()`, not from holding the database. Explicit `BEGIN` is rejected on both surfaces; the runtime owns transaction boundaries.

## Next Steps

* [Quick Start](/docs/edge-compute/sqldb/quick-start) — Create a database, apply a schema, bind it, query it
* [How SQL Databases Work](/docs/edge-compute/sqldb/concepts/how-sqldb-works) — The single primary, sharing, and what durability means today
* [Migrations](/docs/edge-compute/sqldb/migrations) — Versioned schema changes with `storage sqldb migrations`
* [Runtime API](/docs/edge-compute/sqldb/reference) — The `env` binding surface (`SqlDatabase`)
* [CLI Commands](/docs/edge-compute/sqldb/cli) — Create, inspect, and query databases from the terminal
* [Limits](/docs/edge-compute/sqldb/limits) — Size and duration ceilings, and known gaps

## Related Resources

* [Bindings](/docs/edge-compute/runtime/bindings) — How the `env` binding surface works
* [Stateful Actor SQL](/docs/edge-compute/stateful-actors/guides/storage/sql) — The private, per-instance SQLite database
* [KV](/docs/edge-compute/kv) — Key-value storage for read-heavy lookups
* [CLI reference](/docs/edge-compute/reference/cli) — The full `telnyx-edge` command surface
