Concepts

This page covers the building blocks of Pawpado: what each object is, how they relate, and the lifecycle they go through. Read this before you go deep on any specific feature — the rest of the docs assume you know what a session is and how it differs from a pair.

The model

Account (one Huudis identity)
  ├── Credits (one wallet, per-minute debits)
  ├── Tier (which product you're on — decides everything below)
  ├── Storage (persistent tiers only — one EBS volume, per-GB-month debits)
  ├── Saves (throwaway tiers — backed up on stop, restored on start)
  ├── Session (zero or one at a time)
  │     ├── Tailscale registration
  │     └── Pairing (zero or many over the session's life)
  └── Settings (auto-stop, region, preferred hours)

Pawpado is single-instance per user. You can have at most one running session at a time. Trying to start a second while one is running returns an error — the API expects you to stop the first one explicitly.

Tier

The tier is the single most important thing about an account, because it decides whether a machine exists between sessions at all.

Tier Shape Machine What persists
Casual Throwaway 4 vCPU · 16 GB Save files only
Hardcore Throwaway 8 vCPU · 32 GB Save files only
Custom Persistent Any g5 size The whole disk

Throwaway tiers create the machine from a prebaked image when the session starts and destroy it when the session stops. The games are already installed in that image, so there's nothing to download; your save files are backed up before teardown and restored on the next start. Because nothing survives, there is no storage meter and no IP charge — a month with no sessions costs nothing at all.

Custom is the original model: the EC2 instance and its EBS volume are yours, they survive between sessions, and they bill continuously.

Custom also picks which image its disk starts from — the same Casual (200 GB, five games) or Hardcore (500 GB, eight games) image the throwaway tiers use. It only decides what is already installed on day one and how big the volume starts; everything else about Custom is unchanged, and you can install whatever you like on top. Picking the Hardcore image requires a storage plan of at least 500 GB, because the volume is created at the image's size and we will not provision a disk larger than the one you are billed for.

Throwaway sessions run on spot capacity, which is how the price works. Spot is AWS's spare capacity at a deep discount, on the condition that AWS can reclaim it with two minutes' warning. Two minutes is enough to save and re-place a game session and nowhere near enough for a machine that must stay up — which is also why Custom cannot use it.

Placement picks the cheapest capacity that meets the tier's minimum, sorted by price rather than by machine size. In Jakarta a larger machine in one availability zone is routinely cheaper than a smaller one in the other, so you are often placed on a bigger machine than your tier promises, and never on a smaller one.

Account

An account is the Pawpado record attached to your Huudis identity. There's no separate Pawpado password — everything ties back to your Huudis user ID (huudisUserId).

You don't create an account explicitly. It exists the first time you sign in. The dashboard's top-right menu shows the email Huudis returned, and Settings → Account → Delete can purge it (including the EBS volume) if you want to leave.

Session

A session is one streaming desktop — one EC2 instance, one Tailscale registration, one period of compute-meter activity. It progresses through a small state machine:

State Means
idle Nothing running. On persistent tiers storage may still exist.
provisioning Capacity is being placed. Throwaway tiers create a machine from the tier image and restore your saves; persistent tiers attach your existing volume.
starting EC2 instance is booting. Pawpado is polling Tailscale + Apollo for readiness.
running Instance is up. Not yet pairable — wait for ready.
stopping You hit Stop. The meter has already paused. Throwaway tiers back up your saves here before teardown.
stopped Terminal state. Throwaway machines are destroyed; persistent volumes are detached and kept.
failed Something went wrong. The error is surfaced on the dashboard.

SessionStatus also carries a separate boolean: ready. It flips to true only after the Tailscale registration is confirmed and the Apollo streaming server has registered with the control plane. The portal disables the Pair button until ready is true.

Sessions don't have IDs you'll see — there's only ever one at a time per user, so the API exposes singletons (/api/v1/sessions/start, /api/v1/sessions/poll, etc.) rather than typed IDs.

Pairing

A pair authorizes one Moonlight client to talk to the Apollo streaming server inside your session. Pairing is per-device:

  1. Click Pair in the portal — we generate a four-digit PIN.
  2. Type the PIN in Moonlight on the device you want to play on.
  3. Apollo + Moonlight handshake; the device is added to Apollo's known-clients list.

A pair lives for the lifetime of the session. When the session stops, the Apollo allowlist is rebuilt from scratch on the next start — so you'll pair again next time.

The PIN expires in two minutes. If you took too long, request a new one.

Why a fresh pair each session? The Apollo allowlist is part of the EBS volume's state. We deliberately wipe the streaming-server config on session start so a leaked device pairing from yesterday can't connect today. Tailscale tag scoping enforces it even if pairing leaked.

Credits

Credits are your prepaid balance, denominated in IDR (or USD, depending on how you topped up). One wallet per account. Two meters draw from it:

  • Session — per-minute debit while the session is in running, at your tier's hourly rate. On throwaway tiers this is the entire bill: Rp 46,000/hr on Casual and Rp 56,000/hr on Hardcore covers the machine, the disk, the public IP and 1080p on one screen. Higher streaming qualities and extra local-co-op screens adjust the rate; 720p lowers it.
  • Storage — persistent tiers only. Per-minute debit for your EBS volume at Rp 2,000/GB-month, on the full volume size, whether or not you are playing. A static IP adds Rp 85,000/month. There is no free tier.

On a throwaway tier there is no second meter. Stop the session and the balance stops moving entirely.

Credits are managed through Plugipay. Top-ups are checkout sessions: you redirect to Plugipay's hosted page, pay with any method (card, virtual account, e-wallet, QRIS), and Pawpado credits the balance on webhook delivery.

There are no refunds for compute already burned. If you want to leave, you can withdraw unused credit back to your original payment method — see Settings → Credits → Withdraw.

Storage

Storage works differently depending on your tier.

Throwaway tiers (Casual, Hardcore)

There is no storage object and no storage meter. The disk is part of the machine image, sized by the tier, and its cost is already inside the hourly rate. When the session stops the volume is deleted with the instance.

What survives is your saves: before teardown, save files are copied off the machine and restored the next time you start. Anything else you installed during the session does not survive. If you want a persistent library, that is what Custom is for.

Persistent tier (Custom)

Storage is one EBS volume per user, attached to the session while it's running and detached (but kept) while it's stopped. Your installed games (a 100 GB Steam library, say) persist between sessions on this volume.

Storage is billed at Rp 2,000/GB-month on the full volume size (metered per minute) — there is no free tier. You choose the size (200 GB – 1 TB) when you build your machine; you can grow it later (AWS only grows, never shrinks) and the partition extends on your next session start. The size cannot go below the image you built from — 200 GB on the Casual image, 500 GB on the Hardcore one.

You can also snapshot your disk as a save-point at any time (while you have a computer and credit). Snapshots are held at the cheaper Rp 1,000/GB-month rate, billed continuously from creation on their actual stored size, and you can restore or rebuild from one.

If you delete your account, the volume goes too — account deletion is immediate, not deferred.

Grace period & data retention

Grace applies to persistent tiers only. On a throwaway tier there is nothing to hold: when your wallet hits zero the session stops, your saves are backed up as usual, and there is no ongoing charge to fall behind on. Top up whenever you like and start again.

On a persistent tier, when your wallet hits zero Pawpado does not delete anything immediately. Billing pauses, the instance stops, and your storage enters a grace period with two windows:

  1. Live window. Your instance is kept stopped-but-ready, exactly as you left it. A top-up resumes it instantly — no restore step, no reinstall. The live window is 1 day.
  2. Snapshot window. After the live window ends, the root disk is snapshotted and the live volume is released (a snapshot is cheaper to hold than an attached volume). A top-up restores the instance from that snapshot — same library, saves, and mods — on your next start.
  3. Deletion. Only if no top-up arrives by the end of the snapshot window is the data permanently deleted.

How long the snapshot window lasts scales with your lifetime top-ups — the more you've spent on Pawpado, the longer we hold your data:

Tier Lifetime top-ups Live window Snapshot window
Loyal ≥ Rp 500,000 1 day 7 days
New < Rp 500,000 1 day 3 days

The distinction between the two windows is how fast you come back online: in the live window a top-up gives you an instant resume; in the snapshot window the instance is restored from backup on the next start (a short one-time restore). Either way your data is intact.

A single top-up of any amount lifts you out of grace, restores everything, and resets the grace clock — if you later run dry again, you get a fresh full live + snapshot window.

Tailscale connection

Pawpado uses Tailscale to route Moonlight traffic from your device to the GPU instance, peer-to-peer where possible. Every account is a member of the Forjio tailnet (taile685d6.ts.net) under a per-user tag scope.

Per session, Pawpado:

  1. Mints an ephemeral Tailscale auth key scoped to your tag (tag:pawpado-user-<huudisUserId>).
  2. Registers the EC2 instance with that key on boot.
  3. Lets the Apollo streaming server bind to the tailnet IP only — never the public IP.

The ephemeral key expires after 24 hours. When the session stops, the node is removed from the tailnet within a minute.

You'll see the tailnet IP in the API response (tailnetIp), but you don't need to use it manually — Moonlight discovers the instance once you've paired.

Settings

Settings are per-account preferences. The current set:

  • autoStopMinutes — idle-input timeout. Default 15 minutes. Pawpado polls Apollo for last-input timestamp and stops the session when this is exceeded.
  • storageGb — persistent tiers only. The size of your EBS volume in GB (200–1000), chosen when you build your machine. Can be grown later (never shrunk). Ignored on throwaway tiers, where the disk comes with the image.
  • region — AWS region. Defaults to ap-southeast-3 (Jakarta). Other regions are roadmap.
  • preferredHours — not yet enforced; for future scheduled launches.

You change settings via Settings → Preferences in the portal or PATCH /api/v1/settings on the API.

Identifiers

Most Pawpado objects don't expose IDs to you because there's only one of each per account. The exceptions:

Prefix Type Where you'll see it
i-xxxxxxxx EC2 instance ID SessionStatus.instanceId
vol-xxxxxxxx EBS volume ID Admin endpoints, audit logs
cs_… Plugipay checkout session ID When you top up credits

Your Huudis user ID (huudisUserId) is the durable account identifier, but you don't typically interact with it directly — the bearer token carries it.

What this means in practice

The model isn't ornamental — it shapes how integrations work:

  • Polling for readiness. Always wait for ready === true before pairing. Don't trust state === 'running' alone.
  • Idempotent start/stop. Calling start while already running returns the existing session, not an error. Calling stop while already stopped is a no-op.
  • Credit checks. The portal disables Start session when your balance is below ~15 minutes of compute. The API also rejects with INSUFFICIENT_CREDITS if you call start empty.

Once you have this mental model, the rest of the docs are linear: each portal page, each API endpoint, each SDK method maps cleanly to one of these objects.

Next