DeploymentAugust 10, 202613 min read

Coolify and Self-Hosted PaaS vs Managed: What You're Taking On

What you actually take on when the PaaS layer runs on your own server: the maintenance ledger, the one box that holds everything, and when it stops paying off.

RThe Runsite Team

It took an afternoon. A server at a European provider for the price of a couple of coffees, one install command, a dashboard on a subdomain, a repository connected, and a push that came back green. You now have push-to-deploy, preview environments, a Postgres container and TLS certificates that renewed themselves, and the monthly bill went from something with a comma in it to five euros. The natural next thought is that you have been overpaying for years.

That first afternoon is real, and nothing in this article is going to argue you out of it. Coolify is a good piece of software doing a job people need doing, and the same is true of Dokploy, Dokku and the rest of that shelf. The question here is a different one, and it only shows up later: what exactly did you take responsibility for when you ran that install command?

Search for Coolify alternatives and you get the wrong shape of page. Every result compares one self-hosted panel with another self-hosted panel, so the implied question is always "which one do I install", never "should this layer be mine at all". That second question has a real answer, it varies by situation, and for a decent number of people the answer is that self-hosting wins. Working out which group you're in means looking at what actually sits on that server.

What Coolify actually is, and what it isn't

A self-hosted PaaS is a control plane. It watches your Git host, builds images, starts containers, wires up a reverse proxy and shows you all of it in one dashboard. As of writing, Coolify describes itself as an open-source, self-hostable alternative to platforms like Heroku, Netlify and Vercel, which is an accurate description of what it replaces and a slightly misleading one about what it removes. A managed platform is a control plane plus the operations underneath it. Install the control plane on your own machine and you have bought the first half.

That distinction is the whole article, so here it is concretely. This is what sits between your `git push` and a served request when the panel is yours, and who owns each layer. The European Heroku alternative sorted the options into three shapes and left the middle one for later; this is that middle row, opened up.

LayerWho owns it once you self-hostWhat it looks like when it's neglected
Hardware and networkYour IaaS provider (Hetzner, Scaleway, OVHcloud, Exoscale, UpCloud)A hardware incident is handled for you, but the recovery of what was running is not
Operating systemYouUnpatched kernel and packages on a machine with a public dashboard on it
Docker daemon and its storageYouThe disk fills with old images and orphaned volumes, and everything stops at once
Reverse proxy and TLSThe panel configures it, you own the outcomeA renewal that quietly failed, or a routing change that took the dashboard offline with the app
The PaaS control plane itselfYouA version behind on a component that holds your deploy credentials and Git tokens
Your application and its dataYou, on both sides of the fenceThe same as anywhere else, except nobody else is watching the graphs
Six layers, one of which the panel covers. The right-hand column is the part that never appears in a comparison table.

One row of six is what the panel takes off your plate, and it's the row you were most conscious of, which is why the trade feels better than it is. The layers above and below it were being handled by somebody before, and the handover happened silently. This is the same accounting problem self-hosted versus managed PostgreSQL works through for a database: a sticker price you can see, sitting on top of an operational cost you can't. The method there applies here unchanged, so it isn't repeated below. What is different is the ledger, because a control plane fails in ways a database doesn't.

The ledger nobody prices: maintaining the control plane

You can see the shape of this ledger in what people search for after they install. Not "how do I deploy", which the panel solved, but how to update it, how to back it up, how to configure the proxy in front of it, why a certificate stopped renewing, and how to keep the dashboard from being reachable by everyone. Those aren't beginner questions. They're the maintenance surface of the layer you adopted, and each one is an afternoon that arrives without warning.

Updating the platform while it serves production

This is the one with no equivalent on a managed platform, and it's awkward in a way that's hard to design around. Your applications get updated by the control plane. The control plane gets updated by you, by hand, on a machine that is serving live traffic at the time. There is no health-gated rollout for the thing that performs health-gated rollouts, and if an upgrade goes sideways you are debugging the deployment system with the deployment system offline.

In practice most upgrades are uneventful and take ten minutes. The problem is that "most" is doing load-bearing work in that sentence, and the exceptions land on a schedule you don't pick. The reflex response is to postpone, which is exactly how you end up several versions behind on the component holding your deploy keys, your Git tokens and your environment variables.

The proxy, the certificates, and the panel you put on the internet

The panel sets up a reverse proxy and requests certificates, and for a single application with a single domain that really is automatic. It stays automatic until you want something the default template doesn't cover: a wildcard certificate, a second domain on the same service, a websocket route, a header the upstream needs. Then you are editing proxy configuration, and the thing you are editing sits in the request path of every application on the box, including the dashboard you'd use to fix it.

Certificates deserve their own line because their failure mode is delayed. Let's Encrypt issues short-lived certificates by design and expects renewal to be automated, which means a renewal can break in March and you find out in May. Nothing alerts you unless you set up the alert, and the alert is now yours to set up. The dashboard itself is the uncomfortable part: it holds credentials for your Git host, your registries and every environment you deploy to, and by default it wants to be reachable from wherever you are. Putting it behind a VPN or an allowlist is the right answer and it is a piece of work with no relationship to shipping your product.

Disk pressure, and the backup that lives on the backed-up machine

Every build leaves an image behind. Every container that ever ran may have left a volume. Docker does not reclaim any of it until you ask, which is why its own storage documentation has a page on pruning, and on a small server the disk is the resource that runs out first, quietly, over about four months. When it goes, it doesn't degrade politely: builds fail, the database refuses writes, and the panel that would tell you what happened is on the same volume.

Which leads to the backup question, and the answer people give too quickly. Yes, the panel can take scheduled backups. The thing to check is where they're written. A backup on the same disk as the thing it protects covers exactly one failure mode, the one where you delete something on purpose, and none of the others. Getting them off the machine means an external target, credentials for it, a retention policy, and a restore you have actually performed. Object storage that isn't on the machine you're backing up is the cheap part of that list; the restore drill is the part everyone skips.

One box, one failure domain

Self-hosting a PaaS puts every part of your system into a single failure domain, and that is the structural cost of it. The control plane, the reverse proxy, the application containers, the database, the built images and the volumes are all on one machine, usually one disk, under one operating system, reachable through one IP address. A managed setup separates those into different systems because they were built by different teams in different places. Your setup consolidates them because consolidating them is what made it cheap.

text
# One €5 server, after four months of ordinary use.
#
#   the control plane      the thing that would fix the others
#   the reverse proxy      in the request path of everything, dashboard included
#   app containers         prod and staging, because why pay twice
#   the database           on the same disk as the app writing to it
#   built images           every release you might want to roll back to
#   named volumes          including the ones nothing has mounted since March
#   the backups            written locally, because that was the default
#
# Shared: one disk, one kernel, one reboot, one IP.
# Single-tenant is a synonym for single point of failure.

Consolidation has a specific consequence for rollback that carries over from how a deploy pipeline actually works. There, going back to yesterday's release is a lookup: the previous image still exists in a registry, so you point at its digest and start it. On a single box that property holds only while the images are still on the disk, and the disk is the resource under pressure. Every guide to reclaiming space on a full Docker host tells you to prune unused images. Unused images are your rollback targets. The cleanup that saves you on Tuesday removes the escape route you need on Thursday.

Here, rollback is a disk question

A managed platform keeps old releases in a registry that is not your application's disk, so rolling back stays a lookup no matter how full your server gets. Self-hosted, the artifact history and the running system compete for the same gigabytes, and the standard fix for a full disk deletes the history. Worth deciding in advance how many releases back you want to be able to go, and reserving the space for them on purpose.

The recursion is the sharpest version of the same idea. The system that recovers your applications cannot recover itself. If the machine is unreachable, the dashboard is unreachable, and you are back to SSH and whatever you remember about how it was configured. That is a survivable position for someone who set it up last month and a much worse one eighteen months later, on a Sunday, when the person who set it up has left. Putting the database on managed PostgreSQL in a separate failure domain is the cheapest way to break the pattern without giving up the panel, because it moves the one component whose loss is permanent.

Where the GDPR line actually moves

Self-hosting on a German or French server is often framed as the compliance-safe option, and there is something to that: the data sits in the EU on infrastructure operated by an EU company, and the reasoning for wanting that is set out in EU hosting for developers. What changes, and what nobody mentions, is the shape of the paperwork underneath it. You haven't removed a party from the arrangement. You've replaced them with yourself.

  • Your DPA now covers the metal, not the platform. The data processing agreement with your IaaS provider covers what they operate, which is the server. The layer above it is software you administer, so there is no processor to hold accountable for it, because that role is now yours.
  • Breach notification stays with you and gets harder. The GDPR's 72-hour window runs from awareness. With a managed provider, part of your detection capability is their obligation to tell you. Self-hosted, awareness means your own logging and your own alerting on a machine whose logs are on the disk that just failed.
  • Logs, build artifacts and backups are yours to place. These are personal data as readily as the database is. On your own server they land wherever the defaults put them, which is fine while the default is local and becomes a question the moment you point backups at somewhere cheaper.
  • The subprocessor list is one you maintain. Every service the stack touches, from an error tracker to an email relay, is now something you added and something you have to be able to enumerate when a customer's security review asks.

None of that makes self-hosting non-compliant, and it would be dishonest to imply otherwise. Plenty of teams run it properly. It does mean the compliance work moved rather than disappeared, and if the reason you self-hosted was a procurement question about data location, it's worth checking that the answer you now give is one you can evidence. Treat this as the shape of the problem rather than legal advice, and check it against your own counsel before it matters.

What self-hosting genuinely buys you

A comparison that only pointed one way wouldn't be worth reading, and this one doesn't. There are situations where running the panel yourself is the correct engineering decision, not a compromise:

  • The economics invert with the number of applications. One service on a managed platform is priced sensibly. Fifteen small services, half of them internal tools nobody outside the company will ever hit, are much cheaper on one box you already maintain. The per-service cost of a managed platform is its weakest point, and this is where it shows.
  • Arbitrary stacks run without asking permission. A Docker Compose file with six services, a piece of software with unusual networking requirements, a container that needs a device on the host. Managed platforms constrain what you can deploy in exchange for operating it. Self-hosted has no such constraint, which is also why the failure surface is larger.
  • One-click templates cover ground a platform won't. Self-hosted panels ship large catalogues of ready-to-run open-source applications, which is a different product from a place to deploy your own code. If half of what you run is off-the-shelf software, that catalogue is the feature.
  • Internal and homelab workloads have different stakes. A staging environment, an internal dashboard or a personal project has no revenue attached and no customer to notify. The failure domain argument above still applies; it just costs a lot less when it fires.
  • Open source is insurance against terms changing. You can read the code, fork it and keep running the version you have. For teams that have been burned by a licence change, this is not an abstract benefit.

One more signal, and it comes from the self-hosted side of the argument. As of writing, Coolify also sells a hosted edition of itself, where they run the control plane and you don't. That's the same software, minus the six-layer table above, and the fact that the option exists at all is a fair signal about how much of the value was in the panel and how much was in not operating it.

The rest of the shelf, briefly

If you've decided the layer should be yours, the choice of which panel is a smaller decision than it looks, and a fast-moving one, so a feature matrix here would be stale by winter. As of writing: Coolify and Dokploy are where the attention has gone, with Dokploy built around Docker Swarm from the start and therefore easier to spread across more than one node. Dokku is the oldest of them and the most Unix-shaped, driven from the command line with a small footprint. CapRover is a mature Swarm-based panel that has been quieter lately. Kamal, from 37signals, skips the dashboard entirely and deploys containers from a YAML file, which is a different bet: less to run, less to look at. Easypanel is the one people pick for the interface.

Any of them will run your applications. None of them changes the ledger in this article, because the ledger belongs to the server rather than to the panel. Removing the panel and building the pipeline by hand is a further step in the same direction, with its own arithmetic, and it deserves separate treatment. If the question is not whether to host the layer yourself but where to take an existing project that already runs on a managed platform, what leaving Railway actually detaches covers that move instead.

Where the line falls

The useful question isn't which option is cheaper, because the answer to that depends on numbers you can look up in ten minutes. It's what you have more of: services, or people who can fix a server. Those two variables put you in one of a few positions.

Your situationWhat the cost saysWhat the failure domain saysReasonable answer
One or two production services, one developerThe saving is small in absolute termsEverything you have is on one machine you administer aloneManaged. The bill is smaller than the first incident
A dozen services, someone who enjoys infrastructureSelf-hosting wins clearly on per-service costReal, but there is somebody whose job includes noticingSelf-hosted, with backups off the box and the panel not exposed
A dozen services, one developer, no timeSelf-hosting looks like the obvious callOne person, one machine, and no second pair of eyesSplit it. Keep the box, move the database and backups off it
Internal tools, staging, homelabManaged pricing per service is hard to justifyAn outage costs an afternoon, not a customerSelf-hosted, without much agonising
The uncomfortable cell is the third one, because the economics and the risk point in opposite directions.

The third row is where most of the regret lives. The spreadsheet says self-host, the workload says self-host, and the thing that eventually goes wrong is not the platform but the absence of anyone with the time to notice it going wrong. Splitting the difference works better than picking a side: keep the panel for the applications, and move the pieces whose loss is permanent onto something you don't operate.

The question to answer before you install, not after

If this server were gone in the next ten minutes, what would it take to be serving traffic again, and have you done it once? Write down the steps, the location of the backups, and who besides you can perform them. If the honest answer runs past an afternoon or names exactly one person, the number on the invoice was never what you were choosing between.

How Runsite handles it

For the managed side of the trade, concretely: Runsite runs the same push-to-deploy shape and keeps the six layers above off your list. Connect a repository on GitHub, GitLab or Bitbucket and a webhook builds on every push to your branch. The framework is detected automatically for Next.js, Django, Rails, FastAPI and others, and your own Dockerfile is used instead when you supply one. Releases are rolling with a configurable health check gating traffic, a failed check returns to the previous healthy version, and every pull request gets its own environment on its own URL. A deploy takes around 30 seconds as of writing, with the full clone, build and release cycle usually under a minute. HTTPS is automatic on the runsite.app subdomain or your own domain, so no proxy configuration or certificate renewal lands on you. Rollbacks and deploy history are on the Pro plan (€25/mo as of writing).

On the failure-domain question, the pieces are separate services on the same account and the same invoice rather than processes on the same disk: managed PostgreSQL hosted in the EU from €5/mo as of writing, with backups you don't operate, managed Redis for caches and job queues from €5/mo, scheduled jobs, and object storage with no egress charges. Everything runs in Frankfurt, Germany, with containers, environment variables, build artifacts and logs staying inside the EU and a signed GDPR data processing agreement on every plan, including the free one. That last point is the one that matters against the section above: the platform layer has a processor attached to it, and it isn't you.

The free tier is one web service at 0.1 vCPU and 256 MB with auto-deploy from Git and free SSL, and it doesn't cold-start while the application is active, which makes it a reasonable place to park one service from your existing box and compare. Paid web services start at €5/mo and go up to 8 vCPU and 16 GB. Step-by-step setup is in the Runsite docs. A server at any European provider sells raw compute more cheaply, and it always will. The price difference buys five of the six layers off your list, and a rollback history that doesn't live on the disk that fills up.

The short version

A self-hosted PaaS gives you a control plane, which is one layer out of six. The operating system, the Docker daemon and its disk, the proxy and its certificates, the panel itself and everything your application touches stay with you, and the work they generate is real even though no invoice records it. Those layers also share one machine, which means the artifact history you'd roll back to competes for disk with the system that's running, and the tool that would repair everything else can't repair itself. Compliance doesn't vanish either; it changes hands, because the platform layer no longer has a processor behind it. Against that, self-hosting genuinely wins on per-service cost once you have a dozen of them, on arbitrary stacks, and on anything internal where an outage costs an afternoon.

So the decision comes down to two counts: how many services you're running, and how many people can fix the box. If those numbers point in opposite directions, split the difference rather than the price. Move one service onto a European platform that builds and releases on every push and compare what's left on your list, not what's left in your account.

FAQ

Frequently Asked Questions

Common questions about this service.

They fall into two groups, and most comparisons only cover one. The self-hosted group is other panels you install on your own server: Dokploy, which is built around Docker Swarm and is the fastest-growing of them as of writing, plus Dokku, CapRover, Easypanel, and Kamal from 37signals, which drops the dashboard and deploys from a YAML file. Choosing between those changes the interface, not the responsibility, because the server, the operating system, the Docker disk, the proxy and the backups stay yours in every case. The second group is managed platforms, where a provider runs the control plane and the layers under it. European options include Clever Cloud, Scalingo, Upsun and Runsite. Which group you want depends on whether you have more services than people who can fix a server.

The honest answer is that this matters less than it appears, and any feature comparison ages within a couple of releases. As of writing, the clearest structural difference is that Dokploy was built with Docker Swarm in mind, so spreading across more than one node is closer to its design, while Coolify has the larger community and template catalogue. Both give you Git-based deploys, a dashboard and one-click databases on hardware you rent. Neither changes the maintenance ledger: updating the control plane by hand while it serves production, keeping the proxy and certificates working, stopping the disk filling with old images, and getting backups off the machine they protect. If you are picking between them, pick on which interface you would rather debug at 2am, then spend the saved deliberation on where your backups are written.

On the invoice, usually yes, and the gap widens with every service you add, since one server can hold a dozen small applications while managed platforms price each one. On total cost, it depends on a number that isn't printed anywhere: the hours the server takes and what those hours would otherwise have produced. The work is specific rather than vague. Operating system patches, upgrading the control plane by hand on a machine serving live traffic, proxy configuration whenever a default doesn't fit, certificate renewals that fail silently, pruning Docker images before the disk fills, and moving backups somewhere other than the disk they protect. For a dozen services and someone who enjoys that work, self-hosting comes out ahead. For one or two production services and one developer, the saving is small in absolute terms and the exposure is not.

It puts the data in the EU, which is a good start and not the same thing. The arrangement changes rather than simplifies: your data processing agreement with the infrastructure provider covers the server they operate, but the platform layer above it is software you administer, so there is no processor standing behind it. The GDPR's 72-hour breach notification window still runs from the moment you become aware, and self-hosted that awareness depends entirely on logging and alerting you set up yourself. Logs, build artifacts and backups are personal data too, and where they end up is now your decision rather than a documented property of a provider. Teams run this properly all the time. The point is that the compliance work moved onto your side of the line rather than disappearing, and it's worth confirming you can evidence the answers before a customer's security review asks for them.

Your app deserves to be online

Free to start. Deploy in under a minute. No credit card needed.