Skip to content

Loot SQL Preview

Loot SQL is a hosted database designed for limitless horizontal scale and vertically-siloed features.

If you're familiar with SQLite, you already know how to use Loot. A Loot database is a SQLite database that is hosted in a durable object.

Features

  • Declarative schema management: Express your schema as the CREATE statements that lead to the desired database state. Loot diffs and applies non-destructive changes idempotently to existing databases automatically.
  • Read/write access control: Control read and write access with SQL predicates.
  • Flexible tenancy: Create separate databases for each user, feature, chat room, document, or game lobby, or anything else.
  • Idempotent database access: The first time you access a database, it is created. Subsequent accesses to the same database are guaranteed to be the same database.
  • Self-issued security: Authenticate every request with a JWT you sign yourself. No API keys, no need to sign up.

Pricing and Limits

Loot is currently in preview so we can assess interest and iterate on the product. Usage is currently free, but that can change at any time.

We also may break the API at any time, so don't rely on it for anything critical just yet. We'll update this message when we're ready for production.

Schemas, Filters, and Rules

When you access a database, your JWT auth token includes a schema claim. This is a declarative expression of the schema using CREATE statements.

Schemas also manage access control. You can insert rows into the _filters and _rules tables to control read and write access to the database.

Filters

You can insert rows into the _filters table to control which rows are "visible" when executing a statement.

The schema of the _filters table is:

sql
CREATE TABLE _filters (
  -- The name of the table to filter
  table_name TEXT NOT NULL,
  -- The name of the filter
  filter_name TEXT NOT NULL,
  -- The SQL predicate expression that must be true for the row to be visible
  -- (e.g. "user_id = 123")
  predicate TEXT NOT NULL,
  -- Each filter name must be unique per table
  PRIMARY KEY (table_name, filter_name)
);

Statements that would access rows that don't match the filter predicate will succeed with violating rows omitted.

This means that you can use filters to prevent users from accessing rows that they shouldn't be able to see.

Note that if a row is not visible, it cannot be updated or deleted.

Rules

You can insert rows into the _rules table to control which rows can be inserted, updated, or deleted.

The schema of the _rules table is:

sql
CREATE TABLE _rules (
  -- The name of the table to apply the rule to
  table_name TEXT NOT NULL,
  -- The operation allowed by the rule
  -- ("insert", "update", "delete", or "write" for all three)
  operation TEXT NOT NULL,
  -- The name of the rule
  rule_name TEXT NOT NULL,
  -- The SQL predicate expression that must be true for the operation
  -- to be allowed (e.g. "user_id = 123")
  predicate TEXT NOT NULL,
  -- Each rule name must be unique per table
  PRIMARY KEY (table_name, rule_name)
);

Statements that would attempt to insert, update, or delete rows that don't match the rule predicate will fail with an exception stating which rule was violated.

Authentication & Security

Loot has a novel and simple authentication scheme that is easy to implement and secure.

Every request to Loot is authenticated with a self-signed JWT bearer token in the Authorization header.

This way, you can get started using Loot immediately without signing up for an account.

JWTs are signed with a private key that you generate yourself. Each JWK is essentially an account ID which namespaces all accessed databases to your account.

Because JWTs are signed, claims cannot be tampered with. So Loot uses JWT claims as a "privileged" context for security-sensitive things like:

  • Determining which database tenant instance to access
  • Schema management
  • Access control
  • Bypassing filters and rules
  • Destroying databases

Example JWT Payload

js
{
  // The API compatibility date
  "compat": "2025-08-01",
  // The database to execute the request on
  "db": {
    // A name for the database type, as it relates to your application
    "name": "user",
    // A tenant identifier for the database instance (user ID, game ID, chat room ID, etc.)
    "tenant": "123"
  },

  // The schema expression that leads to the desired database state (including filters and rules)
  "schema": `
  CREATE TABLE friends (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL
  );
  
  INSERT INTO _filters
    (table_name, filter_name, predicate)
  VALUES
    ('friends', 'read_all', 'true');
    
  INSERT INTO _rules
    (table_name, rule_name, operation, predicate)
  VALUES
    ('friends', 'write_all', 'write', 'true');
  `,

  // Optional: SQL to be executed before the query
  "before": undefined,
  // Optional: SQL to be executed after the query
  "after": undefined,
  // Optional: SQL to be executed instead of the query, used to bypass filters and rules
  "instead": undefined,
  // Optional: Whether to destroy the database after the query is executed.
  // (This will permanently delete the database and all data, and cannot be undone.)
  "destroy": false
}

Demo

The playground below is a live Loot database. You can define your schema, set up access control, and run queries—all in one place.

The playgrounds on this site create a JWK that's stored in localstorage, and use it to sign a JWT for each request. This means that the databases you see are only accessible to you.

Database
Schema
SQL Query
Results
Initializing...

You can generate your own keypair and JWT using the browser or any JOSE/JWT library. Every request is authenticated by a JWT you sign yourself. No API keys, no registration—just cryptography.