max@blog:~$ cat i-let-claude-migrate-my-production-apps.md
home blog ● online

I Let Claude Migrate My Production Apps

2026-09-09 · 4 min read

With some free time on my hands, and having just completed adding MCP tools to Serversinc, I thought it a best time as ever to battle test those tools via Claude with a couple of my apps I had running on some no-longer-supported Hetzner tiers.

Those apps were Manchester Trams and Manchester Buses, which had been running continuously for around four years on the same server with effectively no downtime. They were both Node.js API managed with PM2 and served through NGINX.

Whilst the setup was reliable, it meant managing them involved SSH'ing into their server, running a rudimentary bash script to update them, and remembering a handful of commands to access NGINX and their own logs.

The move to Serversinc would give me the management and observability layer both apps needed. I'd be able to view their logs from the dashboard (or ask Claude!), check on their health, and manage their configs in one place. It would also mean moving the applications from long-running processes to Docker containers.

Starting with Manchester Trams

Manchester Trams was the first application I moved. Its data was stored in MySQL on the old server, whilst I wanted the new deployment to use Postgres, so the database had to be migrated alongside the application itself.

The agent started by backing up the mcr_trams table from MySQL and converting the exported data into a format that could be imported into Postgres using pgLoader. Before continuing, it checked the converted data against the original to verify that the migration had preserved the records correctly.

Next step was cloning the codebase from Github, building a docker image from it and pushing it to GHCR so the new server could pull the image and start it. From there, the agent used the Serversinc MCP to create the new Application, then paused for me to add Environment Variables and Registry credentials (so it could pull from GHCR) through the dashboard.

Finally, it triggered a deployment and the agent gave me the commands needed to import the converted data into Postgres.

With both versions running, the agent queried the same API endpoints on the old and new hosts to compare their responses. This gave us a straightforward way to verify the migration at the application level, and more importantly, that no one would notice anything from the mobile app's perspective.

Checks passed, and it was onto switching DNS records to the new server. For that it was over to Cloudflare — and a quiet usage period, just after midnight when the trams stop running — where I switched over the A record and watched as service between old and new switched over without a hiccup.

Success!

Manchester Buses

Manchester Buses followed the same process. Its data was prepared for Postgres, the application was packaged into a Docker image and pushed to GHCR, and the agent used Serversinc to configure and deploy the new instance.

As with Trams, the new application could run alongside the existing version while its data and API responses were checked. Once I was happy that the new deployment behaved the same as the old one, I switched its DNS over as well.

The second migration was useful because there was much less to figure out. Manchester Trams had established a migration process that could be applied again with relatively little variation. Back up and convert the data, verify it, package the application, deploy it through Serversinc, import the database, compare the old and new APIs, then cut traffic over.

Finally turning the old server off

Once both applications had been running from the new host for a while and I was satisfied that nothing was still depending on the old machine, I could finally shut down the server they had been living on for the previous four years.

Change request comment

Building something I actually wanted to use

One of the nicest parts of this migration was proving I'd built something I actually wanted for myself. A huge chunk of my day is spent inside terminal agents now, so giving them access to the applications and servers I manage through Serversinc just made sense.

I can ask Claude what an application's been doing, pull its metrics or logs, trigger a deployment, change some configuration, and carry on with whatever I was already working on. The migration was probably the first time I really pushed that beyond a few individual tool calls and let the agent use Serversinc as part of a much bigger job.

It also made something else pretty obvious: deployment wasn't really the reason I wanted to move these applications. Manchester Trams and Manchester Buses barely change. Being able to deploy automatically or tweak configuration from Serversinc is nice, but most of their lives are spent quietly running in the background.

What I actually wanted was to know what was going on. If something restarted, fell over, or started behaving strangely, I wanted Serversinc to notice and give me enough context to understand why without SSHing into a box and starting from zero.

That ended up changing how I think about an important part of Serversinc, which I'll write about sometime in the future.

16 articles · 5.3KB | rss.xml
max@blog:~$ _