Day 2: Deployment to Fly.io
Shipping to production without testing locally—how an AI agent handled Dockerfiles, database provisioning, and the case for personal apps over multi-tenant SaaS.
Skipping Local Testing
I did not test the service locally at all.
I reviewed the code and it looked reasonable enough to work in production. So I told the agent to deploy the service to Fly.io. I chose Fly.io because it can auto‑pause idle services to save cost and resume them on the next network request. It is great for projects under development where there is not much traffic to begin with. This is also the point where I switched from Claude Code for Web to their local CLI. I don’t want to copy and paste my API token to a web portal and risk it being logged or leaked.
Smooth Deployment Experience
The local CC experience was very smooth. With just a single prompt, it managed to install flyctl and fetch an API token from browser login flow. It also generated a multi‑stage Dockerfile and a toml config file for building and deploying the service. I had to tell Claude to provision a database for the Fly.io app in a follow‑up prompt but it quickly figured out that using Fly.io’s unmanaged Postgres is the simplest and cheapest option. Their managed Postgres offering costs $38 a month and had to be called out explicitly to the agent to avoid accidental provisioning.
Debugging the Port Issue
One issue that surfaced after the initial deployment attempt was a warning from flyctl that there was no service listening on port 8080. This was caught by the agent immediately but not acted upon. I prompted the agent to verify that the code is binding to 0.0.0.0 network interface instead of localhost before realising that the Docker runtime was probably missing an EXPOSE instruction to inform Fly.io about the exposed port. Instead of manually hitting the /healthz endpoint to verify this fix, I asked the agent to add a health‑check block to the deployment config to prevent future regression.
In retrospect, I could have probably asked a few more questions so the agent can debug the problem on its own. But since I vaguely remember running into similar problems before, it was much quicker for me to tell the agent where to look. IMO my insights are what separates senior engineers from interns and it would be useful to write them down as an agent skill for future reference.
Agentic Onboarding
Now that the service is live, I asked the agent to convert everything we’ve accomplished together into an onboarding skill for new users getting started. This is where agentic coding has superpowers compared to classical software development. Traditionally, I had to write a bash script that caters to every developer’s local and CI environment. It is always fragile and a pain to maintain. There are an infinite number of configurable options to support and I need to balance the tradeoff between usability and long‑term maintainability. With agent skills, the onboarding instruction can be customised based on the exact environment that the agent is executing in. Less code to maintain is always a good thing.
Security and the Personal App Model
At this point, I realised it is possible to execute the entire onboarding flow securely within Claude Code for Web. There is no manual copying and pasting of tokens into the chat window as flyctl can save the scoped token from browser login flow into a local file inside the sandbox. Claude Code does not need to read the token as it is picked up automatically by flyctl commands. For maximal security, Anthropic could consider making their credentials proxy available for 3rd‑party tools so that agents are physically blocked from reading these files because they don’t exist within the sandbox.
Looking at my agent‑driven deployment setup, it is clear to me that running a multi‑tenant SaaS on homogeneous infrastructure is no longer the only way to distribute your product. In fact, a lot of the software scalability issues disappear if we move to the personal app model where the end user also maintains their copy of the software. It is almost trivial for agents to customise the infrastructure based on the user’s preference and keep the software running on behalf of the user. Most installations don’t need to serve massive amounts of traffic and no code change can cause a global outage because each copy of the software is rolled out as a personal app.