claude-code·8 min read·
Claude Code on Fly.io: a UK indie hacker global-edge worker (2026)
Fly.io gives you a micro-VM in the UK for the price of a coffee a month and scales to zero when idle. Here is how to deploy a headless Claude Code worker pinned to LHR, with GBP costs, scale-to-zero economics, and the Pool B billing notes that matter from 15 June 2026.

A real story. A UK indie hacker built a Claude Code agent that fires once an hour to scan Companies House for new directorship changes against a watchlist. The first version ran on a Hetzner CX11 at GBP 3.30/month, always on. Most of the month the box was idle. The agent ran for 30 seconds out of every 3,600. The honest cost-per-run calculation was embarrassing - the worker was busy 0.8% of the time and idle the other 99.2%.
The redesign uses Fly.io. Same code, same claude -p calls, same OAuth credentials. But the machine scales to zero between runs and the bill drops from GBP 3.30/month to GBP 0.50/month - a 6.6x reduction for a sporadic workload. The same single config line that scales it to zero also pins it to LHR (London), so the Claude calls still go out from a UK IP for any data sources that care.
This is the global-edge bookend to the Hetzner VPS and Raspberry Pi at home posts. The arc is now three Claude Code production hosts: always-on cheap (Hetzner), free at home (Pi), and scale-to-zero on demand (Fly). The matrix in this post tells you which one to pick for which workload.
What Fly.io actually is, in plain English
Fly is micro-VM hosting. You ship a Dockerfile (or let Fly build from a Node/Python/Go project), Fly turns it into a Firecracker VM, and runs it in any of 30+ global regions. The two things that matter for a Claude Code worker are: machines can be configured to scale to zero when no work is happening, and machines can be region-pinned with a one-line primary_region setting.
The pricing model is consumption-based per second of machine time. A shared-cpu-1x machine with 256 MB of RAM costs about USD 1.94/month if it runs 24/7, which is GBP 1.50 at current rates. But if the machine only runs 30 seconds per hour (12 minutes per day), you pay for 12 minutes per day - roughly GBP 0.50/month. The free allowance covers your first 3 shared-cpu-1x machines under 256 MB at low duty cycle.
For a UK indie hacker running sporadic Claude Code agents - hourly scans, daily briefings, occasional Slack-triggered runs - this is the cheapest credible host on the market.
Deploying a headless Claude Code worker to LHR
The minimum viable setup. Three files, one CLI command, the worker is in production.
Dockerfile - install Node, install Claude Code, copy your scripts.
FROM node:22-slim
# Claude Code CLI
RUN npm install -g @anthropic-ai/claude-code
# Workspace for the agent
WORKDIR /app
COPY scripts/ ./scripts/
# Credentials get mounted at boot from Fly secrets
RUN mkdir -p /root/.claude
# Entrypoint script writes the credentials file from the env var,
# then runs whatever scheduled work the machine is here to do.
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
CMD ["/entrypoint.sh"]
entrypoint.sh - hydrate credentials and run the agent.
#!/bin/bash
set -euo pipefail
# Write the OAuth credentials from the Fly secret into ~/.claude
echo "$CLAUDE_CREDENTIALS" > /root/.claude/credentials.json
chmod 600 /root/.claude/credentials.json
# Run the agent. The script can exit when done - Fly will scale us back to zero.
exec node scripts/scan-companies-house.js
fly.toml - pin to LHR and turn on scale-to-zero.
app = "claude-worker-uk"
primary_region = "lhr"
[build]
[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 0
processes = ["app"]
[[vm]]
size = "shared-cpu-1x"
memory = "256mb"
Three commands and the worker is live.
fly launch --no-deploy
fly secrets set CLAUDE_CREDENTIALS="$(cat ~/.claude/credentials.json)"
fly deploy
That's it. The worker now lives in LHR, scales to zero when idle, and starts on demand when something pokes it.
Triggering the worker on a schedule
Fly does not ship a built-in cron. Three ways to trigger:
1. GitHub Actions cron. A .github/workflows/scan.yml with a schedule: block calls fly machine start <machine-id> on the cadence you want. The Fly machine boots, runs the agent, exits, and scale-to-zero returns it. Free if you stay inside the GitHub Actions free tier.
2. Fly machine schedules (preview). Fly's own machine scheduling API lets you set a cron-like rule per machine. Less battle-tested than the GitHub Actions route but no third-party dependency.
3. External cron with an HTTP webhook. A tiny webhook handler on the worker accepts a POST and runs the agent. Any cron source (Hetzner box, Anthropic Routines, Vercel cron, a Linux scheduler) can hit the URL.
The pragmatic default for a UK indie hacker is GitHub Actions cron. It's free up to 2,000 minutes/month, observable in the Actions tab, and version-controlled with the rest of the code.
The GBP cost line, honest
Three workload shapes, three cost outcomes.
Sporadic hourly agent (30s per run, 24 runs/day): 12 minutes/day of machine time = 6 hours/month = GBP 0.50/mo on shared-cpu-1x. Plus the Claude spend. Plus GitHub Actions trigger time, which is free. Total: GBP 0.50 + Claude.
Constant always-on agent (Slack bot, webhook listener): machine runs 24/7 = ~720 hours/month = GBP 1.50/mo on shared-cpu-1x. Beats Hetzner CX11 at GBP 3.30 on raw price - but Hetzner gives you 2 GB RAM and a proper VPS shell. Total: GBP 1.50 + Claude.
Cluster of 5 hourly workers (different jobs): 5 machines, each scale-to-zero, each ~6 hours/month = GBP 2.50/mo. Free tier covers the first 3, so realistically GBP 1.00/mo for the two paid machines. Total: GBP 1.00 + Claude.
Compare with the Hetzner CX11 flat GBP 3.30/mo regardless of workload, or the Raspberry Pi at home flat GBP 0 (after hardware) regardless of workload.
| Host | Always on (GBP/mo) | Hourly agent (GBP/mo) | Notes |
|---|---|---|---|
| Raspberry Pi at home | 0 (hardware GBP 80 one-off) | 0 | Best for indie hackers with hardware + decent home broadband |
| Fly.io scale-to-zero | 1.50 | 0.50 | Best for sporadic UK-region-pinned workers |
| Hetzner CX11 | 3.30 | 3.30 | Best for constant or RAM-heavy workers |
| Vercel function + WDK | included in Pro 16 | included in Pro 16 | Best when you already pay for Vercel Pro and need durable steps |
The decision tree is simple. Always on, RAM-heavy - Hetzner. At home with a Pi - Pi. Sporadic, region-sensitive, scale-to-zero - Fly. Multi-step durable workflow on Vercel - WDK.
The Pool B billing line, honest
The 15 June 2026 Anthropic credit split is host-agnostic. Whether your claude -p invocation fires from Fly, Hetzner, Pi, or a Vercel function, the call lands in Pool B (programmatic) and burns Pool B credits.
The Fly-specific wrinkle is duty cycle. On an always-on host you pay for the machine seconds even when the agent is idle - those seconds are sunk cost regardless of Pool B. On Fly with scale-to-zero, every idle minute costs you nothing. The Pool B burn is therefore the dominant cost line on Fly, not the machine cost. That makes Fly the most Pool-B-efficient host shape for the indie hacker who is already careful about how often they fire Claude calls.
The audit doc for migrating to the split (we are publishing a dedicated checklist later today, see the Pool A vs Pool B migration audit) covers the GBP/month maths under the new pool. The host choice is independent of that audit - pick the host for the workload shape, not for the billing model.
Region pinning and why it matters for UK builders
Three concrete cases where the LHR pin pays off.
1. UK data sources that geoblock. Companies House API, some HMRC sandboxes, certain BBC and ONS feeds either rate-limit harder or outright block non-UK IPs. A worker in LHR avoids the friction.
2. Latency to UK users. A Slack bot for a UK team is sub-30ms from LHR. From Frankfurt or Amsterdam it's 40-60ms. Not catastrophic but noticeable when the agent fires a multi-step interaction.
3. Compliance demonstrability. For UK-shaped GDPR documentation, being able to point at fly.toml and say "the worker runs in LHR, the data never leaves the UK except to call Anthropic" is a clean line. Not legal advice, just a clean line.
Fly makes adding a fallback region trivial. Two lines and your worker runs in LHR by default and falls back to AMS if LHR has a regional outage:
primary_region = "lhr"
regions = ["lhr", "ams"]
What goes wrong (and what to do about it)
Three real failure modes from running this setup for a month.
Cold start latency. Fly machines that scaled to zero take 200-800ms to boot when poked. For a Slack bot this is noticeable but acceptable. For a sub-100ms HTTP API it is not. The fix: either keep min_machines_running = 1 and pay the always-on price, or add a tiny warmer that hits the URL every few minutes.
OAuth credential expiry. claude OAuth credentials refresh themselves but the refresh writes back to ~/.claude/credentials.json. On a scale-to-zero machine the file is recreated from the Fly secret on every boot, so a fresh refresh inside the machine is lost. Two fixes: rotate the secret periodically with fly secrets set CLAUDE_CREDENTIALS="$(cat ~/.claude/credentials.json)", or write the refreshed credentials back to a Fly volume that persists between machine restarts. The volume option is cleaner.
Outbound rate limits from a single Fly IP. Multiple workers from the same Fly app share the same outbound IPs. Some third-party APIs (especially scraping targets) will rate-limit aggressively. Fly machine cloning to a second region (AMS, CDG) gives you a different outbound IP for free.
The UK indie hacker default
The recommendation, after running this in production for the last fortnight.
- Fly.io scale-to-zero for any agent that fires less than once every 5 minutes and benefits from a UK region pin. The economics dominate at low duty cycles.
- Hetzner CX11 for any agent that runs constantly or needs more than 256 MB of RAM. Flat-rate beats scale-to-zero at high duty.
- Raspberry Pi at home for personal agents where you do not want a third-party hosting bill at all.
- Vercel WDK for multi-step workflows with human-in-the-loop pauses.
Pick by the shape of the workload, not by religious attachment to one host. The Claude Code Agent SDK runs identically on all four. The OAuth credentials, the headless claude -p invocations, and the Pool B billing on 15 June are host-agnostic. The host choice is purely about price-per-duty-cycle and proximity-to-data.
The wider point. Fly.io fills the scale-to-zero, region-pinned gap in the UK Claude Code production lineup. For sporadic agents, it's the cheapest credible host. For constant agents, it's beaten on price by Hetzner but offers global edge as a bonus. For UK builders specifically, the LHR pin is one config line and unlocks the geoblocked UK data sources that other hosts make harder to reach. That makes it the right default for any agent that fires hourly or less, anywhere a UK IP buys you something.
New here? IdeaStack publishes one deeply researched UK business opportunity every Thursday - real keyword data, competitor analysis, builder prompts. See the latest free report.
Frequently asked
Why deploy a Claude Code worker to Fly.io instead of a Hetzner VPS or Raspberry Pi?
Three reasons. First, Fly.io pins your worker to LHR (London) and gives you a micro-VM in 30+ regions for the same price - if the worker ever needs to follow users elsewhere you swap one config line. Second, Fly's machines scale to zero between runs, so a worker that fires once an hour pays only for the seconds it ran, not for an always-on box. Third, Fly's free shared-cpu-1x machine tier costs GBP 0 for the first 3 machines under the free allowance, and a paid LHR machine with 256 MB of RAM runs about GBP 1.50/mo if you exceed it. For a sporadic agent loop, that's cheaper than a GBP 3.30 Hetzner CX11 sitting idle. For a constantly-running agent, Hetzner wins on price - the matrix matters.
How do I pin a Fly machine to the UK?
Set primary_region = 'lhr' in fly.toml and Fly schedules your machine in London (Heathrow). For redundancy or proximity to non-UK users, list extra regions under regions = ['lhr', 'ams', 'cdg']. Inside the machine, your Claude calls go out from a UK IP, which matters for any UK-specific data sources (Companies House, HMRC sandboxes, GOV.UK APIs that geoblock) and for compliance angles where you need to demonstrate UK-resident processing. The fly deploy command picks the primary_region by default; fly scale count and fly machine clone let you spin up regional replicas on demand.
What does this cost in GBP per month for a typical indie hacker?
A scale-to-zero worker that fires the Claude CLI once an hour for 30 seconds per run costs roughly GBP 0.50 in machine seconds (24 runs/day at 30 seconds = 12 minutes/day, GBP 0.005 per minute on shared-cpu-1x). The free tier covers your first 3 machines under 256 MB. The Claude spend itself lands in Pool B from 15 June 2026 - a hourly Sonnet research call at 4k tokens is roughly 2p per run, so GBP 14/month for 720 runs. Total: GBP 16-17/month all in. Compare with always-on Hetzner CX11 at GBP 3.30/mo + Claude spend - for sporadic agents Fly wins, for constant agents Hetzner wins.
How does Fly handle the Pool B billing split that lands on 15 June 2026?
Fly is the host, not the biller for Claude calls. Your `claude -p` invocations on Fly hit the same Pool B credit that they would on Hetzner, on a Raspberry Pi, or on a Vercel function. The 15 June split is about how Anthropic counts programmatic vs interactive Claude usage, not about where the worker runs. The audit checklist for migrating to the split (which calls land in Pool B, what your GBP/month looks like under the new pool) is the same regardless of host. The Fly-specific wrinkle: scale-to-zero matters more under Pool B because every machine-second you pay for while idle is wasted GBP.
What about OAuth and authentication inside a Fly machine?
Same pattern as any headless Claude Code worker. Run `claude /login` once locally, copy the credentials JSON into a Fly secret with `fly secrets set CLAUDE_CREDENTIALS=$(cat ~/.claude/credentials.json)`, then write the file at container start. The credentials are tied to your account, not to a host - they work identically on Fly, Hetzner, or any other Linux box. The ARM64 OAuth workaround documented for Raspberry Pi (GitHub issue #27405) does not apply to Fly because Fly machines are AMD64 by default. If you do force ARM64 (Fly does offer it for cost), the same workaround applies.
Filed under




