Database

Typed schema. Migrations on save.

Declare entities in TypeScript with field.string / int / datetime / id and composite indexes. Pylon diffs the schema and applies migrations automatically. SQLite by default — one file, zero setup. Point DATABASE_URL at Postgres and the same schema follows.

schema.ts
import { entity, field } from "@pylonsync/sdk";

const Room = entity("Room", {
  slug: field.string(),
  name: field.string(),
  createdAt: field.datetime(),
});

const Message = entity("Message", {
  roomId: field.id("Room").readonly(),
  authorId: field.id("User").readonly(),
  body: field.string(),
  createdAt: field.datetime().readonly(),
});
  • One schema file, fully typed — your editor knows every field
  • Migrations apply on save in dev; no migration files to hand-author
  • SQLite is the default: a single file, nothing to provision
  • Set DATABASE_URL=postgres://… and the same schema targets Postgres
01

Field types that mean something

field.id("Room") is a typed foreign key, field.richtext() carries formatting, field.datetime() is timezone-correct, field.encrypted() is sealed at rest. Add .readonly() to block HTTP PATCH from rewriting identity fields, .index() for composite indexes. The types flow all the way to db.useQuery on the client.

02

SQLite to Postgres without a rewrite

Prototype on SQLite — it's a file, it ships in the binary, there's nothing to stand up. When you need Postgres (via PlanetScale on Cloud, or your own), set one environment variable. The schema, the queries, the policies, and the sync engine are identical; only the storage target changes.

03

Migrations you don't babysit

Change a field, save the file, and Pylon diffs the live schema against your declaration and applies the migration. In production the same diff runs as a guarded step on deploy. No migrations/ folder full of timestamped SQL to keep in order.

Build it on Pylon.

One framework for your schema, sync, auth, functions, realtime, and SSR. Free to start.