STATEWAY

STATEWAY

Documents at the edge. Guarantees you can name.

A Durable Object owns each partition — so conditional writes and counters are real. Talk to it with native /v1, or keep boto3 and Cosmos when you must.

One object. One partition. No home region.

Stateway runs on Cloudflare Workers and Durable Objects. Schema in a catalog, data in SQLite per partition — not a single-region cluster you fan out to later.

Strong where it matters
Inside a partition key: serialised requests, conditional writes, atomic counters, local indexes, single-partition transactions.
Honest where it ends
Global indexes and full-collection scans are eventually consistent. Cross-partition atomicity is two-phase commit — or you stay in one partition.
Same bytes, three wires
Native JSON, DynamoDB, and Cosmos DB share one store. Write with /v1, read with an SDK — or the other way around.

Where partition-strong wins.

Pick a partition key that matches how you race: a tenant, a user, a room, an account. Inside that key, reads and writes are serialised. Across keys, stay eventual or pay for two-phase commit.

Multi-tenant product state
Partition on tenantId. Config, entitlements, and feature flags update with if_version — no lost write when two admins save at once.
Edge sessions and preferences
Keep per-user documents next to the Worker that serves them. Conditional puts and TTL cover login, cart drafts, and prefs without a home-region round trip.
Counters, quotas, and balances
Atomic increments live inside the partition. Rate limits, seat counts, and wallet-style balances stay correct under contention without a separate lock service.
Orders and workflows per account
Hash on the customer (or order aggregate). Single-partition transactions cover place / cancel / inventory adjust as one atomic unit; cross-account moves use /v1/transact.
Realtime rooms and game state
One Durable Object per room or match. Presence, scores, and turn state are strongly consistent for everyone keyed to that room — without inventing your own coordinator.
Move Dynamo or Cosmos to the edge
Keep boto3 or @azure/cosmos pointed at api.stateway.dev. Same documents as native /v1, so you can migrate clients one path at a time.

Poor fit: analytics scans across every tenant, or workloads that need a strongly consistent global secondary index on every write. Prefer a warehouse or a regional store for those.

What /v1 already covers

Collections, items, query and scan, indexes with real CREATINGACTIVE status, streams, TTL, batch, and single- or multi-collection transactions.

Full reference in the getting started guide and repo docs/native-api.md.

Three ways in. One document.

Start on native /v1. Keep boto3 or @azure/cosmos when an existing client already speaks them — endpoint https://api.stateway.dev.

import { Stateway } from "https://stateway.dev/client.js";

const sw = new Stateway({
  endpoint: "https://api.stateway.dev",
  token: process.env.STATEWAY_TOKEN,
});

await sw.createCollection({ name: "orders", hash: "pk", range: "sk" });
await sw.put("orders", { pk: "acme", sk: "o#1", total: 42.5 });
const { item } = await sw.get("orders", { pk: "acme", sk: "o#1" });
import boto3

ddb = boto3.client(
    "dynamodb",
    endpoint_url="https://api.stateway.dev",
    region_name="us-east-1",
    aws_access_key_id=STATEWAY_AKID,
    aws_secret_access_key=STATEWAY_SECRET,
)

ddb.put_item(
    TableName="Orders",
    Item={
        "customerId": {"S": "acme"},
        "orderId": {"S": "o#1"},
        "total": {"N": "42.5"},
    },
)
import { CosmosClient } from "@azure/cosmos";

const client = new CosmosClient({
  endpoint: "https://api.stateway.dev",
  key: process.env.COSMOS_MASTER_KEY,
});

const { database } = await client.databases.createIfNotExists({ id: "shop" });
const { container } = await database.containers.createIfNotExists({
  id: "orders",
  partitionKey: { paths: ["/customerId"] },
});
await container.items.create({
  id: "ord-1",
  customerId: "acme",
  total: 42.5,
});

Invite-only. Production already up.

Hosted Stateway is not a public signup. If you have credentials, set STATEWAY_TOKEN to your secret and hit /v1. Health and latency budgets live at api.stateway.dev/health.