All posts

Should your app and database run on the same server?

Ross Hill · September 13, 2026

Yes, for most applications. Running your app and its database on the same machine is a normal production setup, not a shortcut you have to apologize for. It stops being the right call for a handful of specific, nameable reasons, and knowing those reasons is more useful than a rule of thumb either way.

This post is about the architecture and the latency. The money argument for putting several projects and databases on one box is a separate post: how to run several side projects on one server covers the per-service billing arithmetic and how to size the machine. What follows assumes you have already decided the cost side makes sense, and asks whether the design does.

We sell single-VM hosting, so we have an interest in the answer. The list of reasons to split below is the honest version, not a shortened one.

What "same server" actually means

Two shapes, and the distinction matters less than people expect.

The classic one is PostgreSQL installed on the host, with the application connecting over a Unix domain socket or over 127.0.0.1. The modern one is both the app and the database running as containers on the same host, talking to each other over a Docker bridge network by container name.

Neither puts a switch, a router, or a span of fibre between a query and its answer. The packets are handled by the kernel on one machine. That is the entire technical basis for the latency argument, and it is worth being precise that this is a local connection rather than a no network connection: a container-to-container hop still traverses a virtual bridge and a network namespace. It just never leaves the box.

What the network hop actually costs

A single query's round trip across a network is small in absolute terms. Cloud providers publish figures for this, and they are good figures.

AWS describes Availability Zones in a region as being up to 60 miles apart but "close enough to use synchronous replication with single-digit millisecond latency". Microsoft publishes measured medians between Azure regions. In its round-trip latency statistics, the figures published in August 2026 put the P50 from Canada Central to Canada East at 13 ms, and Canada Central to East US at 18 ms. Those are Microsoft's numbers, measured on their backbone, not ours.

Single-digit milliseconds inside a region is a well-engineered network doing its job, and enormous production systems run happily on exactly that arrangement. One hop is not the problem. Web requests rarely issue one query.

AWS's figure is about synchronous replication between Availability Zones rather than an app's query round trip, and a same-AZ hop is faster still, but it sets a useful floor. Call it 1 ms for arithmetic, which makes the numbers below the optimistic case for splitting. A request that issues 40 sequential database queries, each waiting on the previous one, spends 40 ms doing nothing but waiting for the network. The same 40 queries against a database on the same host pay a fraction of that per hop, because there is no physical link to cross. Now move the database to another region instead of another zone. At Microsoft's published 18 ms median between Canada Central and East US, those same 40 sequential queries cost roughly 720 ms of pure waiting, before the database has done any actual work.

None of that makes your database faster. It changes the penalty for query patterns that are already slightly wrong:

  • N+1 queries. An ORM lazily loading a related record inside a loop turns one logical operation into dozens of sequential round trips. This is the single most common way a page ends up latency-bound rather than CPU-bound.
  • Chatty request handlers. Auth check, feature flag lookup, user record, permissions, then the actual query. Five round trips before anything interesting happens.
  • Connection setup. A TCP handshake plus a TLS negotiation is several round trips before the first query is even sent. Connection pooling amortizes this rather than erasing it, and pools get exhausted at exactly the wrong moments.

The correct fix for N+1 is to fix the N+1. Colocation is not a substitute for that. It does mean a mistake of this kind degrades a page instead of breaking it, which is a real operational difference when you are shipping quickly with a small team.

When colocation is the right call

Colocation fits when your app and your database scale together, which describes most small and mid-sized applications:

  • One application, one database, growing at roughly the same rate.
  • A workload where a bigger machine solves the next capacity problem.
  • A team that would rather operate one server well than two adequately.
  • A data residency requirement where you would rather verify one location than two. If the app and the database live on the same VM in Toronto, there is exactly one jurisdiction question to answer.

When it is the wrong call

Be honest about these, because they are not edge cases.

You need independent scaling. If your database is CPU-starved while your app servers are idle, or the reverse, one machine forces you to buy both. Splitting lets each grow on its own curve.

You need high availability or automatic failover. One machine is one failure domain. If the host dies, the app and the database die together, and your recovery time is however long a restore takes. Multi-node database services exist because some workloads cannot accept that. If a few hours of downtime would be a business problem rather than an annoyance, this is the reason to split.

Your dataset is genuinely large. Once the database wants more disk, memory, or sustained IO than a single reasonably-sized VM provides, the co-tenancy stops being free. Your app is now competing with the page cache.

You need more than one app server. The moment a second application instance exists, the database has to be reachable from off-box anyway, and the colocation argument evaporates.

Separation is a compliance or contractual requirement. Some agreements specify where and how data is stored independently of the application. If a contract says the database is separate, the architecture question is already settled.

Two things to get right if you colocate

These two do most of the risk reduction.

Backups, because everything is now in one place. Losing the machine means losing the app and the data at the same time, so database-level backups off the server are not optional. On MapleDeploy, Coolify's built-in database backups write to any S3-compatible bucket on a schedule and retention count you set. Pick that bucket's region deliberately: a backup is a full copy of your data, so a bucket in the US puts that copy under a second jurisdiction no matter where the VM sits. Choose a Canadian region, or at least a non-US one, if residency is why you are here.

MapleDeploy also takes best-effort weekly snapshots of the whole VM, plus one before any termination. That pre-deletion snapshot is kept for 30 days after cancellation. The weekly ones go with the VM. Treat all of them as our safety net rather than yours: they are not guaranteed, they can be up to seven days old, and they are a disaster recovery layer rather than a granular restore tool. Our backup guide has the setup steps and the honest limits of each layer. Test a restore, not just the backup job.

Resource limits, because your own workloads are now each other's neighbours. A runaway build or a memory leak in the app can starve the database on the same host. Coolify exposes per-resource memory and CPU limits for exactly this, and setting them once is cheaper than diagnosing an out-of-memory kill at 2am.

How this works on MapleDeploy

MapleDeploy runs managed Coolify on a dedicated VM in Toronto. PostgreSQL is one of Coolify's one-click databases, and it runs as a container on the same VM as your application. Coolify hands you an internal connection string that points at the database container by name, resolved over the Docker network on that host, so the app-to-database traffic stays on the machine by default. The database is not published to the internet unless you deliberately expose it through Coolify's TCP proxy with a public port.

What you do not get as a one-click feature is multi-node failover, read replicas, or point-in-time recovery beyond your configured backup schedule. You have root on the VM, so you can build those yourself, but Coolify will not manage them for you. If you want someone else operating database high availability, a dedicated managed service is the better tool, and where to run managed PostgreSQL in Canada compares the Canadian-region options honestly, including the ones that beat us on that specific axis.

Colocate by default. Split when you can name which of the reasons above applies to you.

Run your app and database on one Canadian VM

One-click PostgreSQL next to your app, on a dedicated Toronto server. 30-day free trial on Starter and Pro.