The backend that survives the restart
JustScale is a general-purpose TypeScript backend framework: you write plain, straight-line code, the compiler makes long-running work durable, domain code never sees a string ID, and the same code scales from one instance to many. Like Go, where blocking code just scales, for TypeScript.
npx create-justscaleReal createProcess wrap, real imports, real types. Hover anything in the panel — Monaco resolves it against the live @justscale/* type definitions.
Six things JustScale does that other frameworks don't
The differences are mechanical, not marketing.
Durable Processes
Workflows that suspend on signals or timeouts and resume after restarts. Plain async code, transformed by the compiler into an opcode-based state machine.
ID-Free Domain
No string IDs in domain code. A persistent entity is its own reference. Storage owns IDs; your code passes typed entities and lets the compiler check the rest.
Distributed-Safe by Construction
Mutations require Locked<T>. Acquiring a lock is atomic with the read. The same domain code runs against an in-memory lock locally, and Postgres advisory locks across 20 nodes — without changing.
Transport Agnostic
Define routes once. Same controller serves HTTP, WebSocket, gRPC, CLI, and SSE. Same DI, same middleware, same guards.
If it Compiles, it Works
Missing dependency? Type error. Bare Persistent<T> passed to update? Type error. Locked<T> sent across the wire? Refused at serialization time.
No Runtime Magic
No decorators, no reflect-metadata, no proxies you can't reason about. defineService takes a plain object. The token IS the class. What you read is what runs.
From async to durable, in three steps
The compiler does the work. You write what happens.
1. Declare the signals
Path-based, typed, routable. The path IS the topic.
Distributed-safe, by construction
Every mutating repository method requires Locked<T>. The only way to get one is to ask the repository, which acquires the lock atomically with the read. The same code runs against an in-memory lock locally and a Postgres advisory lock across 20 nodes — without changing.
If it compiles, it works. Pass a bare Persistent<Account> to accounts.update? Type error. Try to send a Locked<T>across the wire? The serializer refuses — locks don't survive process boundaries, so pretending they do would be a lie.
Wire it up
Domain, infra, app. Three layers. Domain code never imports infra. Swap Postgres for in-memory in tests without touching a service.
Explore the JustScale documentation
In a JustScale backend you write plain, straight-line code and it just scales - from one instance to many. Each guide below shows how one piece fits together, from durable processes to the ID-free domain model.
Durable processes
Long-running workflows written as plain async code that survive a process restart, a deploy, or a node failure.
Signals
Path-based, typed events that suspend and resume a durable process exactly where it left off.
ID-free domain
Model your domain with type-safe references instead of the loose string IDs a backend usually has to validate by hand.
Type-states
Let the shape of your data decide what your code is allowed to do, with the compiler enforcing every transition.
Services & DI
Type-safe dependency injection that wires your application together without manual plumbing or container boilerplate.
Controllers & routes
Group HTTP, CLI, and WebSocket endpoints into controllers that stay type-safe from request to response.
Locks & concurrency
Distributed locking that keeps concurrent access safe across every instance of your backend, not just one.
PostgreSQL adapter
Persist your models, processes, locks, and channels on PostgreSQL through a single, swappable adapter.
Testing
Spin up real applications inside your tests and prove the distributed invariants hold before you ship.
Ready to write t-shirt code?
The installer detects your package manager and IDE, scaffolds a project, and gets you to just dev in under a minute.
npx create-justscale