Guides
Ephemeral test server

Ephemeral test server

Need a real Minecraft server for a few minutes — to run an integration test, validate a plugin, or let an agent try something — then throw it away? This is exactly what metered + scale-to-zero billing is for. You pay for the minutes it's awake and nothing for its existence.

A 4 GB server awake for a 5-minute CI job costs ~5 minutes of GB-hours. Created-but-never-started, or deleted right after, it rounds to nothing.

The pattern

Create (cheap, stopped)

import { TrueTickClient } from "@truetick/sdk";
const client = new TrueTickClient(); // TRUETICK_API_KEY
 
const server = await client.servers.create({
  name: `ci-${process.env.GITHUB_RUN_ID ?? Date.now()}`,
  ramMb: 4096,
  type: "PAPER",
  version: "1.21.1",
  plan: "metered",
});

Start and wait for running

await client.servers.start(server.id);
 
// Poll until ready (Paper cold start ≈ 12s)
for (let i = 0; i < 60; i++) {
  const s = await client.servers.get(server.id);
  if (s.state === "running") break;
  await new Promise((r) => setTimeout(r, 2000));
}

Run your test

Drive the server over RCON and assert on real behavior + honest metrics:

await client.console.run(server.id, "say test harness online");
 
const m = await client.servers.metrics(server.id);
if (m.live && m.tps < 19) {
  throw new Error(`TPS regression under test: ${m.tps}`);
}

Tear down (always)

await client.servers.delete(server.id);

Put the delete in a finally so a failed test still cleans up — otherwise the server keeps billing while awake (until idle hibernation kicks in).

Full CI script

import { TrueTickClient } from "@truetick/sdk";
 
const client = new TrueTickClient();
const name = `ci-${process.env.GITHUB_RUN_ID ?? Date.now()}`;
let id: string | undefined;
 
try {
  const server = await client.servers.create({ name, ramMb: 4096, type: "PAPER", version: "1.21.1" });
  id = server.id;
 
  await client.servers.start(id);
  for (let i = 0; i < 60; i++) {
    if ((await client.servers.get(id)).state === "running") break;
    await new Promise((r) => setTimeout(r, 2000));
  }
 
  // … your assertions over RCON / metrics / logs …
  const { output } = await client.console.run(id, "list");
  console.log(output);
} finally {
  if (id) await client.servers.delete(id);
}

CLI variant

The CLI's init --create / down pair gives you the same ephemeral lifecycle for plugin work, and it marks the server ephemeral so down knows it's safe to delete:

truetick init --create --name "ci-run" --ram 4096 --type PAPER --yes
truetick deploy            # build, upload, restart, confirm the jar loaded
# … run tests against the server …
truetick down --yes        # delete the ephemeral dev server

See Deploy a plugin for the deploy half, and Programmatic control for agents for the agent angle.