The lifecycle of an app.nz cloud machine
Provisioning is more than create: app.nz tracks provider ids, machine status, ready times, termination, simulated providers, and cleanup for CPU and GPU infrastructure.
Listen to this article
On-device voiceUses the voice built into your browser; no article text leaves this page.
Audio narration is not supported by this browser.
Provisioning is where the app.nz control plane becomes real infrastructure. A row in the database turns into a machine at a provider, an SSH target, a Docker host, a GPU pod, or a notebook runtime.
The important thing is to make the lifecycle explicit.
The provision request
The internal request carries the provider, region, machine type, image, labels, user, and startup intent. The provider implementation turns that into a Hetzner server or RunPod pod.
That abstraction is small on purpose. app.nz does not need to hide every provider detail. It needs enough common shape to create, observe, and terminate machines reliably.
CPU and GPU providers differ
Hetzner CPU machines are good for coding agents, CI, builders, notebooks, and ordinary server tasks. They are provisioned with cloud-init, SSH setup, and the runtime packages needed for the worker.
RunPod GPU machines are good for cogs, Comfy, video, and notebook sessions that need CUDA. They need image selection, registry auth, exposed ports, and provider proxy URLs.
Treating both as "machines" is useful. Pretending they are identical is not.
The instance row
app.nz stores cloud instances with provider, machine type, region, status, label, image, provider id, IP, created time, ready time, and terminated time. That row is the source of truth for billing, status pages, and cleanup.
The provider id is especially important. It is the handle needed to terminate the real machine. A machine without a stored provider id is hard to clean up.
Ready is not created
Providers often return success when a resource exists, not when the app is usable. app.nz separates created, ready, and terminated timestamps.
For billing and UX, those are different events:
- created: provider accepted the resource,
- ready: the runtime can handle work,
- terminated: billing should stop after final accounting.
Notebook sessions, cogs, and Comfy deployments all benefit from that distinction.
Simulated providers for tests
The server has simulated paths for tests and local development. That matters because provisioning code touches money and external APIs. Unit tests should validate state transitions and handlers without creating real machines.
The trick is to keep simulation faithful enough to exercise the lifecycle:
insert instance mark ready expose fake provider id meter time terminate
Cleanup is part of provisioning
Provisioning is not done when the machine starts. It is done when app.nz can terminate the machine and prove it stopped being billable.
That is why every feature that creates machines needs an idle reaper, manual stop path, failure cleanup, and usage meter. "Start" without "stop" is not infrastructure. It is a leak.