Quickstart
Run a function once across several processes, then hand work from a producer to a worker and get the result back, in TypeScript or Python.
In this quickstart you run a few small programs against the hosted service:
- a function wrapped with
once, started from two terminals at the same time, that runs only once; - a queue with a worker that handles jobs and a producer that submits one and waits for its result.
The programs can be in different languages. Pick a tab once and every code sample on the site follows it.
1. Get a space and an API key
Section titled “1. Get a space and an API key”- Sign in to the console at app.getrunstate.com (closed while the preview is paused) and open a space (a project or environment). Copy its space id.
- Open API keys in that space and create a key. The secret is shown once, so copy it now.
2. Install the SDK
Section titled “2. Install the SDK”Node.js 22 or later.
mkdir runstate-quickstart && cd runstate-quickstartnpm init -ynpm pkg set type=modulenpm install runstate-sdknpm install --save-dev tsxPython 3.10 or later. The package installs as runstate-sdk and imports as runstate.
mkdir runstate-quickstart && cd runstate-quickstartpython -m venv .venv && source .venv/bin/activatepip install runstate-sdk3. Set your credentials
Section titled “3. Set your credentials”Set these in every terminal you use below:
export RUNSTATE_SPACE_ID=<your space id>export RUNSTATE_API_KEY=<your api key>export RUNSTATE_RUN=quickstartThe SDKs connect to https://api.getrunstate.com by default. RUNSTATE_RUN names the run that every process joins. Processes with the same run name share results and work.
4. Run something once
Section titled “4. Run something once”import runstate from 'runstate-sdk';
const research = runstate.once(async function research(company: string) { console.log(`researching ${company}...`); await new Promise((resolve) => setTimeout(resolve, 5000)); // slow work return { company, summary: `${company} makes widgets` };});
console.log(await research('acme'));Start it in two terminals at the same time:
npx tsx once.tsimport time
import runstate
@runstate.oncedef research(company: str) -> dict: print(f"researching {company}...", flush=True) time.sleep(5) # slow work return {"company": company, "summary": f"{company} makes widgets"}
print(research("acme"))Start it in two terminals at the same time:
python once.pyOnly one terminal prints researching acme.... Both print the same result. Start it a third time and the result comes back at once, without running the function: the result belongs to the quickstart run.
5. Define a queue
Section titled “5. Define a queue”A queue hands work to worker processes. Define it in one module that both sides import.
import runstate from 'runstate-sdk';
export const double = runstate.queue('double', async (input: { n: number }) => { return { doubled: input.n * 2 };});import runstate
@runstate.queue("double")def double(input: dict) -> dict: return {"doubled": input["n"] * 2}6. Write the worker and the producer
Section titled “6. Write the worker and the producer”import runstate from 'runstate-sdk';import './jobs.ts';
console.log('worker ready');await runstate.serve(); // handles jobs until Ctrl-Cimport { double } from './jobs.ts';
console.log(await double({ n: 21 })); // submits the job and waits for the resultimport runstate
import jobs # noqa: F401 (defines the queue)
print("worker ready", flush=True)runstate.serve() # handles jobs until Ctrl-Cfrom jobs import double
print(double({"n": 21})) # submits the job and waits for the result7. Run it
Section titled “7. Run it”Start the worker in one terminal:
npx tsx worker.tspython worker.pyRun the producer in a second terminal:
npx tsx producer.tspython producer.pyThe producer prints:
{ doubled: 42 }(Python prints {'doubled': 42}.) Stop the worker with Ctrl-C. It finishes the job in hand before it exits.
The two sides are interchangeable: a TypeScript producer works with a Python worker and the other way round, because both talk to the same API.
What just happened
Section titled “What just happened”- The run. Every process joined the run named
quickstart. The first call created it; the others joined it. Results and jobs belong to that run. - once hashed the arguments into a key. The first caller ran the function; the other waited and got the same result. Had the first process crashed, the other would have taken over.
- The job is durable. If the producer had crashed while waiting, submitting the same input again in the same run returns the same job and its result, without running the handler again.
- The worker held the job under a lease that
serve()renewed while the handler ran. Had the worker died mid-job, the lease would have lapsed and another worker would have picked up the job.
To start over with fresh results, stop the run with runstate.stop() or use a different RUNSTATE_RUN.
Next steps
Section titled “Next steps”- Concepts: the vocabulary behind runs, once, limits, slots, budgets and queues.
- Once and queues: results, retries and crash takeover in detail.
- Configuration & auth: every client option and key permission.