Case study

Off a managed backend, onto a server they own

A dashboard for tracking student rosters across online courses. Moved because of arithmetic, not ideology — and delayed by something that had nothing to do with code.

Why they moved

The app worked. That is worth saying first, because it is usually true and usually beside the point. Course curators used it daily to manage student lists. Nothing was broken.

What prompted the move was a calculation. The agency that built it worked out that within about six months the app would cross the platform’s free limits, and their client would be on a monthly subscription from then on — indefinitely, and rising with usage.

Set against that, a one-off migration onto hardware the client already owned and was already paying for stopped being a philosophical question about vendor lock-in and became a spreadsheet.

The ownership benefits came along for free: a database they can back up themselves, and no third party between them and their data.

Scoped before anything was touched

The plan went out first: seven items, an estimate, and an explicit list of what was not included. That last part matters more than it sounds. It is the difference between a handover and an argument.

Work started the same day it was agreed.

What moved

Four services, one compose file.

01

The front end

The React build, containerised and served from the client’s own machine rather than a vendor’s hosting.

02

The scheduled function

A serverless function fired on a schedule by an external cron. It became an ordinary cron service running inside the same server — same job, one less thing owned by someone else.

03

The database

The managed Postgres behind Supabase became a Postgres the client owns, with access moved onto a backend layer instead of being reached through a vendor SDK.

04

The routing layer

Nginx in front of everything, so requests reach the right service — and so the next application on that box does not collide with this one.

Five hours of work, spread over rather longer

This is the part worth being honest about, because it is the part that repeats on almost every job.

The technical work took about five hours. The elapsed time was considerably more, and none of the difference was engineering. We were waiting on SSH keys, and then on the password for the Linux account we needed. Nothing can start until those exist, and they usually live with whoever set the server up originally.

So the useful thing to know before commissioning any migration: the work is short, the access is the long pole. Gather the credentials first and the whole thing compresses into a day.

The one thing that did surprise us

The client’s server was not empty. Other applications were already running on it, and the obvious ports were taken. Not a hard problem — the services were moved to free ports and Nginx routes to them — but exactly the kind of thing that turns into an outage when someone assumes a clean machine and starts a container that fights an existing one.

A migration onto shared infrastructure is a different job from a migration onto a blank server, and it should be treated as one.

The result

We came to Alexandr to move an application we had built for a client from cloud infrastructure onto the client’s own server. By our estimates the client would have hit the platform’s limits within six months and been pushed onto a monthly subscription.

Alexandr and his team started the same day and delivered exactly to the plan and the deadlines they had given us up front. We’re happy with the work — accepted it straight away, no issues at all. We’ll be coming back to them.

Stasagency partner

What we would tell you honestly

This one went cleanly because the scope was written down before work started. Not every job looks like that. Where an app leans hard on proprietary pieces, a migration turns into a partial rewrite — and we say so before taking the work rather than after.

Get a quote

Same situation?

Tell us what you built and where it runs. You get back whether it can be moved, what the real scope is, and a fixed price — usually within one business day.

No newsletter, no automated sequence. Your details are used to answer you and nothing else.