---
title: "Run one instance per core"
description: "Run one instance of your server per core with cluster.run, restart without dropping a request and stop cleanly on SIGTERM."
section: "guides"
status: "Building for 0.4"
spec: "parallelism"
canonical: "https://mainsdk.dev/docs/guides/run-one-instance-per-core"
updated: "2026-10-28"
---

# Run one instance per core

> Run one instance of your server per core with cluster.run, restart without dropping a request and stop cleanly on SIGTERM.

Status: Building for 0.4 · Canonical: https://mainsdk.dev/docs/guides/run-one-instance-per-core · Updated: 2026-10-28

You will start your server once per core on one shared port, roll a restart through the instances and let the primary stop them through the drain. It takes about 10 minutes and needs no account.

## You need

- A long-running Node server that listens on a port. Serverless, edge and Deno run one process.
- For limits and broadcasts that count once per host: `runtime.store.driver: local` (the default).

## 1. Declare the cluster

```yaml title="main.yaml"
cluster:
  processes: auto
  start-timeout: 30s
health:
  shutdown: { deadline: 25s }
```

## 2. Start through cluster.run

```ts title="start.ts"
import { cluster } from "mainsdk";

declare function startServer(): Promise<void>;   // your own server entry, such as the one that calls listen()

await cluster.run(startServer);
```

The primary forks the instances and serves nothing. Each instance runs your server, and the primary routes connections only to instances that listen. In `mainsdk dev` and on serverless it runs one process and logs `MAIN-WORKER-0014`.

## 3. Roll a restart

Send SIGHUP to the primary, or call `cluster.restart({ reason: "deploy" })`. Each slot gets a new instance, waits until it is ready, then shuts the old one down through the drain. A new instance that is not ready in time stops the roll with `MAIN-WORKER-0013` and the old instances keep serving.

## 4. Stop

SIGTERM to the primary starts the normal drain in every instance. The primary waits for `health.shutdown.deadline` plus 2 seconds, then ends what is left, and exits 0 only if every instance exited 0. An instance that crashes is respawned after the backoff (`MAIN-WORKER-0011`); a slot that crashes `crashes` times in `window` stops (`MAIN-WORKER-0012`).

## Check it worked

- Requests show several process ids, never the primary's.
- `cluster.snapshot()` lists every instance as `ready`.
- A restart replaces every pid and no request fails.
