Deployment

Multi-node Coolify + SurrealDB Deployment

Load-balanced multi-server model: SSL termination at the edge, round-robin to identical servers, clustered SurrealDB data tier.

DeploymentCoolifyMulti-nodeLoad balancer

This page describes a scaled-out reference deployment for Crown using:

  • a self-hosted Forgejo delivery plane for source control and webhooks
  • a self-hosted OCI registry for private image storage
  • Coolify's documented multi-server operating model, specifically the multiple domains across multiple servers approach from the scalability docs
  • distinct domain groups routed directly to workload server A and workload server B, each with its own Coolify-managed proxy
  • separate workload hosts for frontends, APIs, and jobs
  • SurrealDB's documented multi-node scalable cluster mode backed by TiKV

Official references:

Reference topology

Multi-node Coolify + SurrealDB deployment
Multi-node Coolify + SurrealDB deployment

Source: multi-node-coolify-surrealdb-deployment.mmd

Flow order

Multi-node Coolify + SurrealDB deployment flow
Multi-node Coolify + SurrealDB deployment flow

Source: multi-node-coolify-surrealdb-flow.mmd

This sequence view shows both halves of the model: the one-build-to-many-servers deployment flow and the runtime request flow where DNS sends a hostname to the specific workload server that owns that domain set.

Why this pattern exists

The official Coolify scalability docs show two traditional horizontal-scaling shapes:

  • one domain across multiple servers
  • multiple domains across multiple servers

Coolify generally recommends the one-domain option as the simpler default. For Crown, this reference intentionally models the multiple-domains option instead, because that maps better to a platform with several frontends and APIs that can be placed deliberately on different machines.

Separately, the SurrealDB docs describe the TiKV-backed cluster mode as the option for highly-available and highly-scalable setups.

Putting those together gives a sensible Server A / Server B scaling path for Crown:

  • treat self-hosted Forgejo and the registry as delivery infrastructure, not app features
  • keep one control plane for deployment management
  • spread workloads over multiple runtime hosts with per-server proxies and per-server domain ownership
  • move the data tier to the SurrealDB clustering mode that was actually designed for scale

How to read the diagram

This reference splits the platform into five concerns:

1. Delivery services

The self-hosted delivery plane holds:

  • Forgejo as the Git provider and webhook source
  • a dedicated Coolify build server that performs image builds away from runtime hosts
  • a private OCI registry that stores deployable artifacts

If you use Forgejo's built-in container registry, the registry endpoint can live on the Forgejo instance domain. If you use a separate registry product, the deployment flow is still the same: builder pushes, Coolify pulls.

Coolify's multiple-server docs add one more important detail: when a deployment needs a build, Coolify builds the image once on the main server or the dedicated build server, pushes that image to the registry, and only then tells the workload servers to pull and deploy it.

2. Control plane

The Coolify server holds:

  • project and environment configuration
  • deployment targets
  • deploy coordination

It does not need to sit in the public request path for every Crown hostname.

3. Workload server A

Server A is one domain-serving pool:

  • it runs its own Coolify-managed proxy
  • DNS sends a specific set of Crown hostnames directly to that server
  • that local proxy then routes those domains to the frontend and API containers placed on Server A

This is the key difference from the single shared-load-balancer model: the server owns the domains it serves.

4. Workload server B

Server B works the same way:

  • it has its own Coolify-managed proxy
  • DNS points a different domain set at it
  • it can host additional frontends, APIs, and jobs behind that local proxy

Because each server can host multiple apps, this model can be cost-efficient — but it also means bigger servers may be needed as you consolidate more domains and workloads onto a single machine.

5. Clustered data tier

The official SurrealDB multi-node guide uses TiKV as the backing store. In practice, that means thinking about the data layer as two parts:

  • SurrealDB query nodes that Crown talks to
  • TiKV cluster nodes that provide the distributed storage layer

The diagram intentionally abstracts the exact TiKV quorum sizing, but it shows the architectural truth: once you want the official scalable-cluster mode, SurrealDB is no longer just one local file on one host.

Important SurrealDB nuance

The SurrealDB TiKV page uses a single-node development TiKV cluster in its example and explicitly frames that as being for development and testing purposes only.

That matters for Crown.

For real production multi-node deployments, you should treat the TiKV layer as a real distributed data platform with its own:

  • sizing decisions
  • redundancy model
  • backup and restore procedures
  • observability
  • upgrade plan

In other words: the multi-node app topology is only half the story. The data tier must also be production-grade.

Traffic pattern

In this reference shape:

  • developers push to the self-hosted Forgejo instance
  • Coolify dispatches the build once to the dedicated build server
  • the build tier publishes versioned images to the self-hosted registry
  • Coolify pulls those images onto workload hosts
  • DNS points one hostname set directly at Server A's proxy and another hostname set directly at Server B's proxy
  • each workload server terminates HTTPS locally through its own Coolify-managed proxy
  • each local proxy routes only to the containers placed on that server
  • Crown services talk to an internal database endpoint rather than a single pinned machine name
  • that internal endpoint fans into multiple SurrealDB query nodes
  • those nodes share the TiKV-backed cluster state

There is no single shared public ingress in front of all Crown domains in this reference. The domain split is the traffic-distribution mechanism.

Coolify-specific operational caveats

The Coolify docs call out a few details that matter here:

  • the multiple servers feature is still marked experimental
  • each deployment server — and the optional build server — should use the same architecture
  • every server that needs to pull images must be authenticated to the registry via Docker credentials
  • the extra per-server proxy adds a small amount of overhead, though the docs note this is usually not noticeable
  • health checks in this pattern are effectively server-level, not a single shared application-level load-balancer health model

When to choose this pattern

Choose the multi-node pattern when:

  • one server is no longer enough for the combined workload
  • you want domain-based placement, where specific Crown hostnames live on Server A or Server B
  • you want workload isolation between frontends, APIs, and background jobs
  • maintenance or failure on one machine should not take out the whole platform
  • the database workload justifies the operational complexity of a distributed data tier

When not to choose it

Do not choose this pattern just because it looks impressively enterprise on a diagram.

Avoid it when:

  • the current workload fits comfortably on a single host
  • the team does not have operational ownership for clustered databases yet
  • the main pain point is build speed rather than runtime scale
  • you want one shared public entrypoint with central app-level load-balancer health checks

If the real issue is build pressure, the Ubuntu / Coolify hosted deployment pattern with a dedicated Coolify build server is usually the better next move.

Crown recommendation

For Crown, this Server A / Server B pattern is the right second-stage scaling model when you specifically want the Coolify multiple-domains-across-multiple-servers approach:

  • keep Forgejo and the registry in the delivery plane rather than on app nodes
  • use Coolify to manage multiple workload hosts
  • give each workload host its own proxy and its own domain set
  • keep runtime images immutable and registry-driven
  • expose only the per-server proxy layers publicly
  • front SurrealDB query nodes with an internal endpoint
  • treat TiKV as a separately operated production subsystem

That gives Crown a credible path from “single box, simple ops” to “multiple hosts, deliberate domain placement” without inventing a custom platform story from scratch.