Lifecycle & wake-on-join
TrueTick servers are scale-to-zero. An idle server hibernates — it stops consuming CPU/RAM and stops billing — and comes back online the moment someone needs it. This is the mechanism behind metered billing: you pay for runtime, not for a box sitting idle.
States
A server moves through a small set of states, reported in state:
| State | Meaning |
|---|---|
stopped / hibernated | Scale-to-zero. Not running, not billing. Data preserved |
starting | Container booting / world loading |
running | Live and serving players. Billing accrues (metered plan) |
stopping | Graceful shutdown in progress (world saved) |
installing / install_failed | Modpack pre-install in progress / failed (see Mods) |
You drive transitions with start, stop, and restart. Always treat state as the source of
truth and poll it after a transition rather than assuming instant completion.
Wake-on-join
A hibernated server has a lightweight proxy listening on its Minecraft port. When a player connects to
my-smp.truetick.gg:25565, the proxy:
- Parses the connection handshake.
- Boots the real server container.
- Hands the player through once it's ready.
The player sees a brief "waking up" experience instead of a dead address. No API call is needed — this is automatic. The sleeping proxy also answers the server-list ping with a MOTD and a sleep line, so the server still looks alive in the multiplayer list.
Programmatic wake. If you want to bring a server up without a player joining (e.g. before a
scheduled event, or in a CI job), call POST /v1/servers/{id}:start. Same boot path, triggered by
you instead of a join.
Cold start
Boot time depends on the core and content:
- Vanilla / Paper / Purpur: typically ~12 s to ready.
- Modded (Forge/NeoForge/Fabric with mods): longer — large modpacks take minutes on first boot, and TrueTick allows up to a 10-minute start window for modded servers.
After boot, the readiness check confirms the server is actually accepting players before marking it
running.
Idle hibernation
When a server has had no players for idleTimeoutMinutes, the idle watcher hibernates it back to
scale-to-zero. Set the timeout per server via setProperties(id, { idleTimeoutMinutes }). A shorter
timeout saves money on bursty workloads; a longer one avoids re-waking during brief lulls.
Putting it together
A typical metered lifecycle:
create (stopped, $0)
→ player joins ──► wake-on-join ──► running (billing)
→ empty for idleTimeoutMinutes ──► hibernate (stopped, $0)
→ player joins again ──► wake ──► running …For an agent or CI workflow that controls timing explicitly:
await client.servers.start("ci-test"); // cold start (~12s for Paper)
// … poll until state === "running", run your tests …
await client.servers.stop("ci-test"); // stop billing immediatelySee Billing for how runtime maps to cost, and the Ephemeral test server guide for the CI pattern end to end.