Declarative schema, live sync, TypeScript functions, and tick-based game shards — as a single Rust binary. Run it on a VPS, AWS, or Cloudflare Workers.
No migrations, no glue code, no separate realtime layer. The same server runs your app queries and your game ticks.
{"Message": {"fields": {"channelId": "id<Channel>","authorId": "id<User>","body": "string","createdAt": "timestamp"},"indexes": [{ "on": ["channelId", "createdAt"] }]}}
import { mutation } from "pylon/server";import { z } from "zod";export const send = mutation({args: {channelId: z.id("Channel"),body: z.string().min(1).max(4000),},handler: async (ctx, { channelId, body }) => {const me = await ctx.auth.require();return ctx.db.insert("Message", {channelId,authorId: me.id,body,createdAt: Date.now(),});},});
import { db } from "@/pylon/client";export function Channel({ id }: { id: string }) {const messages = db.useQuery("Message", {where: { channelId: id },order: "desc",limit: 50,});const send = db.useMutation("send");return (<Pane><List items={messages ?? []} /><Composer onSubmit={(body) =>send({ channelId: id, body })} /></Pane>);}
Everything below ships in pylon. No sidecars. No extra Redis. No separate realtime layer. Either lane is useful alone; together they're rare.
JSON schema with refs, indexes, and per-field validators. Migrations auto-generated.
Queries are WebSocket subscriptions by default. Subsecond fan-out, no polling.
Queries and mutations run server-side with Zod validators. Types flow to the client.
Magic codes, OAuth (Google, GitHub, Apple), sessions, row-level policies — no separate service.
Authoritative 20/30/60 tps loops in Rust. Deterministic. Snapshot + delta replication.
Room-based matchmaking, area-of-interest filtering, backfill, late-join, observer slots.
Durable background jobs, cron, and multi-step workflows with retries. Survive restarts.
Row-level policies as code. One rule enforces reads, mutations, and shard inputs.
Start on a laptop, end on a managed cluster — without rewriting a handler. The storage driver is pluggable; everything above it is identical.
SQLite backend, hot-reload, type-safe client regen. Zero config to start.
Ship the same binary to a $5 box. Built-in TLS, embedded storage, graceful restart.
Run on Cloudflare Workers with Durable Objects for shards. Scale-to-zero, global by default.
Included Terraform module: ECS services, Aurora Postgres, ALB, secrets. Your VPC, your keys.
Pick an app backend ora game server and you'll stitch the other in. pylon ships with both primitives, sharing auth, storage, and policies.
Opinions that shape how the whole system feels. If these don't sound right for your project, that's fair — pick something else.
handler is the transaction.No BEGIN, no COMMIT, no stale-read bugs. The whole mutation runs under serializable isolation and auto-retries on conflict.
BEGIN;SELECT balance FROM accts WHERE id = $1;UPDATE accts SET balance = balance - $2 ...;UPDATE accts SET balance = balance + $2 ...;INSERT INTO transfers ...;COMMIT;
export const transfer = mutation({handler: async (ctx, { from, to, amount }) => {const a = await ctx.db.get(from);await ctx.db.patch(from, { bal: a.bal - amount });await ctx.db.patch(to, { bal: a.bal + amount });await ctx.db.insert("Transfer", { from, to, amount });},});
Not just games. A collaborative canvas is a 30 tps simulation. Live cursors are presence events at 60 tps. An agent swarm is a deterministic step function.
Reads hit a local mirror first; writes queue optimistically and reconcile on reconnect. Offline by default, no extra config.
No account, no API keys, no waitlist. If you have cargo and a browser, you're set.
Grab the CLI with cargo. One binary — no services, no Docker required.
Scaffolds schema, server functions, and a typed client.
Starts the server, watches your code, regenerates the client on every save.
Mount the client anywhere you already have React. Queries are reactive by default.
❯ cargo install pylon-cliCompiling pylon-cli v0.8.2Finished release in 41.2s❯ pylon --versionpylon 0.8.2