Agentic hosting is here. Connect to our MCP now ->

Blog

Every project has its own deployment process. That's the problem

When every project has its own deployment process, your team pays for it on every release. Here's what that costs and how to standardize it.

·by Steve McDougall

"How do we deploy this app?"

That's a question I've heard time and time again on teams that ship more than one app or project. There's no standardisation. Each one is unique, with its own quirks, and each one needs its own deployment process, usually one that nobody really wrote down.

We all look to the same person: the project lead who set it up. They're now seven projects past that initial deployment, and the details get hazier each time. Was it this one that had a separate process for background processing, or was it the one before that?

If you're lucky, they made notes. If you're really lucky, they wrote them down somewhere like Notion. I won't go down the unlucky route, as I think we've all experienced it at least once.

I'm talking about teams that might be running several production applications at the same time. The main product, maybe a couple of client builds, an internal tool or two, each with real users that depend on it. One app with a messy deploy is what I would call an annoyance. Seven of them is the way that your whole team is operating.

What the snowflakes cost

So the cost doesn't show up as a line item on an invoice, instead it shows up in the time between someone asking "How do we deploy this app?" and someone being confident enough to actually press the deploy button.

Take onboarding for example, a new developer doesn't learn how the team deploys projects, because there isn't one singular way. They learn how this project deploys, then how the next one does, then the quirks of the one after that. They just followed the process for a different project, again and again.

Then there's the deploy that goes wrong because the steps were a little different this time around. Running the migrations before the new code goes live is fine on one project, do the same on another and for some reason everything just breaks. Nobody made a mistake, they just followed the process from a different project.

Then the project lead goes on holiday. Deploys can't stop, but they definitely slow down. People will wait, or they will message someone who is meant to be switched off. Or they push the release to the next week, or the week after. One person taking annual leave turns into a delivery risk for every project they set up initially.

None of this is dramatic on its own. Added up across seven projects and a growing team, it's a lot of time spent remembering how to ship instead of actually shipping.

How every project ended up somewhere different

Nobody actually sits down and decides to run seven different projects on four different hosts. It happens one project at a time.

The first app went onto AWS, because that's what the company was using, or what the first engineer knew. The marketing site went onto Vercel, because it was quick and someone had used it before. A client project landed on DigitalOcean because the budget was tight and a droplet was cheap. Another went onto Google Cloud because it came with credits.

Each decision made sense at the time. Each one was made by whoever was setting up the project, for that project, without anyone looking at the bigger picture. Each one came with its own way of deploying: a GitHub Actions workflow here, a push to deploy there, and an SSH script on the droplet that only the person who wrote it really understands.

Add it all up and you don't have a deployment process anymore. You have seven of them, spread across four different platforms, each with its own dashboard, its own logins, its own billing, and its own quirks. That's the pile the project lead is trying to remember when someone is asking how a certain project is deployed.

Seven deployment processes is operational debt

Teams like to call this flexibility. Every project got the tools that suited it best at the time, so what's the real harm? The harm is that you now owe maintenance on all of it, and the maintenance burden just keeps adding up.

It goes well past the deployment notes. There are seven pipelines, each with its own secrets, its own runner versions, and its own idea of what actually happens before a deploy. Some projects have a staging environment, some might not, and one has a staging droplet that nobody has updated since it was first created. Environment variables live in four different dashboards, and a couple of .env files on servers. Someone has to patch the droplet from time to time, someone also has to keep the IAM roles on AWS sensible, and SSL certificates renew through whatever mechanism each host happens to use. When something breaks, the logs are in three or more different places.

Every change you want to make gets made seven times, seven different ways. Upgrading PHP across all servers turns into a separate project for every app, and like any debt, it gets called in at the worst possible moment: during an incident, or when a security patch lands, or when the one person who understood that SSH script hands in their notice.

One operating model for every project

Now, if every one of these projects were running on Sevalla, how would that look? Would we still need to do a frantic search for notes?

Luckily, using Sevalla, we can simplify this down to a Dockerfile, a Procfile, or a nixpacks.toml. Our deployment process is Git. How each app is built and which processes it runs are part of the project, in files that sit right next to the code, and a Dockerfile is one you can run locally too. It's simpler, it's straightforward, and it's self-documenting. We no longer have to hunt down the project lead and hope they wrote it all down.

The build files are only the start though. What really changes is that every application now runs in the exact same way. Each one will move through a pipeline with the exact same stages, from development to staging to production, and in a trunk-based setup you promote a build to the next stage instead of rebuilding it. Pull requests can get their own preview app, which is cleaned up when the pull request is closed. Every project has the same Analytics, the exact same logs, the same scaling controls, and the same hibernation settings. All in one dashboard, on one bill. The CLI and API work the same way for every single app too, so anything you script for one project will work for all of the rest of the projects.

That's the operating model. Your team only has to learn it once, and uses it on every project, and Sevalla handles the infrastructure underneath all of them. There's no droplet to patch, no IAM to untangle, and no certificate renewal to remember.

Same platform, same moving parts

The projects still won't all be the exact same. One might need a queue worker, or another runs the scheduler, and maybe another needs a cache or a different database. What changes though, on Sevalla, is that those differences stop living in someone else's memory.

Each extra piece is a process, set up on the same Processes page every time in every project. A queue worker is just a background worker running php artisan queue:work. The Laravel scheduler will run as a background worker too, but with php artisan schedule:work. Anything that should run on a timer and then stop is a cron job process. If you would rather keep that list inside the code, a Procfile in the repo does the same job, so the processes are written down where the next engineer will look.

The platform handles everything underneath: building the images, running the pods, routing the traffic, scaling, and recovering when something falls over. The team still decides what each project needs. Which processes it will run and with what start command, how big each pod is, how many instances it gets, its environment variables, and which database or cache it will connect to. Those decisions get made once, in the same place for every project, instead of being rediscovered every time someone asks how the app gets deployed.

When a project should keep its own process

Not all projects belong on the same platform. Some genuinely need their own setup.

A frontend that's purely static, with no server-side code, might be better left where it is. A project with strict data residency or compliance rules might have to run somewhere very specific, whatever the convenience cost. A client might own their hosting account and insist on it. Now and then a project needs something unusual, a runtime or piece of infrastructure that a general platform simply doesn't offer.

What those have in common is a reason. "The client required it" or "the data has to stay in this region" is a decision. "That's just where it ended up" isn't a decision, and for most of the projects on the list of seven, that's likely the most honest answer.

Move one project and hand it to someone new

I want you to pick a project with the vaguest of deployment notes. The one where "How do we deploy this app?" gets maybe the longest pause, and maybe no answer.

Move it onto Sevalla. Connect the repo, add the processes it needs, whether that is a background worker for the queue, another for the scheduler or a cron job for anything on a timer, and set the environment variables. If you'd rather keep the processes in the code, put them into a Procfile.

Hand it to someone who has never deployed it before, and ask them to ship a small change without talking to the project lead, making sure to time it. Make a note of every question they had to ask, and where they found the right answer.

Do the same with one of the projects that is still spread across the old setup, and compare the two. The gap that is between those lists is the cost you have been paying on every project, every time someone new picks one of them up.

Next time someone asks "How do we deploy this app?", the answer should be "the same way as all the others".

Deep dive into the cloud!

Deploy your application, database, or static site in minutes.