NEWPylon Cloud — deploy anywhere, idle at $0

The backend for
real-time apps and games.

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.

View on GitHub★ 2.4k
apps/chat/App.tsx
useQuery·live
#engineering
M
J
R
D
M
maya5m
shipping the v0.8 tick loop tonight
J
jonas3m
pulled it — tests pass on my laptop
R
rhea1m
useQuery fires in 4ms here, sub is instant
>type a message
apps/chat/Channel.tsxTSX
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>
);
}

Schema. Function. Subscribe.
Or: simulate, host, play.

No migrations, no glue code, no separate realtime layer. The same server runs your app queries and your game ticks.

// collaborative chat — ~60 LOC server, ~20 LOC client
1. Declareschema.jsonjson
{
"Message": {
"fields": {
"channelId": "id<Channel>",
"authorId": "id<User>",
"body": "string",
"createdAt": "timestamp"
},
"indexes": [
{ "on": ["channelId", "createdAt"] }
]
}
}
2. Writefunctions/chat.tsts
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(),
});
},
});
3. SubscribeChannel.tsxtsx
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>
);
}

Two lanes, one binary.

Everything below ships in pylon. No sidecars. No extra Redis. No separate realtime layer. Either lane is useful alone; together they're rare.

App

Declarative schema

JSON schema with refs, indexes, and per-field validators. Migrations auto-generated.

App

Real-time sync

Queries are WebSocket subscriptions by default. Subsecond fan-out, no polling.

App

TypeScript functions

Queries and mutations run server-side with Zod validators. Types flow to the client.

App

Auth, built-in

Magic codes, OAuth (Google, GitHub, Apple), sessions, row-level policies — no separate service.

Game

Tick-based shards

Authoritative 20/30/60 tps loops in Rust. Deterministic. Snapshot + delta replication.

Game

Matchmaker + AoI

Room-based matchmaking, area-of-interest filtering, backfill, late-join, observer slots.

App + Game

Jobs & workflows

Durable background jobs, cron, and multi-step workflows with retries. Survive restarts.

App + Game

Policies

Row-level policies as code. One rule enforces reads, mutations, and shard inputs.

Same binary. Same code.
Four deploy targets.

Start on a laptop, end on a managed cluster — without rewriting a handler. The storage driver is pluggable; everything above it is identical.

01

Laptop

pylon dev

SQLite backend, hot-reload, type-safe client regen. Zero config to start.

SQLite
02

VPS

systemd · one binary

Ship the same binary to a $5 box. Built-in TLS, embedded storage, graceful restart.

docker run
03

Workers

cloudflare edge

Run on Cloudflare Workers with Durable Objects for shards. Scale-to-zero, global by default.

scale-to-zero
04

AWS ECS + Aurora

terraform apply

Included Terraform module: ECS services, Aurora Postgres, ALB, secrets. Your VPC, your keys.

terraform

The only option that does both well — in one process.

Pick an app backend ora game server and you'll stitch the other in. pylon ships with both primitives, sharing auth, storage, and policies.

For appsvs. app-backend stacks
Feature
pylon
Convex
Supabase
Firebase
Declarative schema
Live queries
TypeScript functions
Self-hosted, one binary
Authoritative game loop
No vendor lock-in
For gamesvs. game servers
Feature
pylon
Colyseus
Playroom
Nakama
Tick-based authority
Area-of-interest
Matchmaker included
Declarative app data
Live queries for UI
Self-hosted, one binary
first-class partial / via extension not supported

Three choices you won't find elsewhere.

Opinions that shape how the whole system feels. If these don't sound right for your project, that's fair — pick something else.

01

The 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 });
},
});
02

Tick-based shards for anything with a loop.

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.

useShard("canvas")30 tpsuseShard("cursors")60 tpsuseShard("agents")10 tpsuseShard("match")20 tpsuseShard("mmo_zone")15 tps
03

Local-first sync with an IndexedDB mirror.

Reads hit a local mirror first; writes queue optimistically and reconcile on reconnect. Offline by default, no extra config.

client · ▇▇▇▇▇▇▇▇▇▇▇▇ reads 0.4ms
mirror · ▇▇▇▇▇▇▇▇▇▁▁▁ indexeddb
socket · ▁▁▁▁▁▁▁▁▁▁ deltas
server · ▇▇▇▇▇▇▇▇▇▇▇▇ source of truth
offline · writes queued, reads from mirror

Four commands to a running backend.

No account, no API keys, no waitlist. If you have cargo and a browser, you're set.

01

Install

Grab the CLI with cargo. One binary — no services, no Docker required.

02

Init a project

Scaffolds schema, server functions, and a typed client.

03

Run dev

Starts the server, watches your code, regenerates the client on every save.

04

Open the browser

Mount the client anywhere you already have React. Queries are reactive by default.

shellsh
cargo install pylon-cli
Compiling pylon-cli v0.8.2
Finished release in 41.2s
pylon --version
pylon 0.8.2