Twenty Services in One Repository

A microservices monorepo makes refactoring, contract changes, dependency upgrades, and onboarding easier. It can also give you the worst of both worlds: tightly coupled code, long CI pipelines, and twenty services redeployed for a one-line frontend change.

The repository, the build system, and the deployment platform must agree on the same dependency boundaries.

Two configuration mistakes cause most of the wasted work. The first is setting the application root path to the service subfolder, which removes shared packages from the Docker build context. The second is omitting deployment restrictions, which lets every commit trigger every service.

The Five Rules

Each of the five rules maps to a Qovery feature:

  1. Build from the repository root. Leave the application root at the repository root and point the Dockerfile path to the service. Shared packages and the lockfile stay in the build context, and turbo prune keeps the final image small.
  2. One Qovery service per deployable. One application per long-running service, one lifecycle job per migration workflow. Scaling, health checks, secrets, and rollbacks stay independent.
  3. Deployment triggers follow the dependency graph. Deployment restrictions in MATCH mode let each service redeploy only when its own code, or a shared package it actually imports, changes.
  4. Order the pipeline by dependency. Databases, then migrations, then core services, then the edge. Independent services share a stage and deploy in parallel.
  5. Choose what each preview runs. In the blueprint environment, skip the services a pull request does not need, so previews stay cheap.

The qovery-monorepo-microservices repository tree, with apps/*/Dockerfile annotated "One Dockerfile per app" and packages/ annotated "Shared code"
The qovery-monorepo-microservices repository tree, with apps/*/Dockerfile annotated "One Dockerfile per app" and packages/ annotated "Shared code"

Define the Contract in Terraform

The Qovery Terraform provider exposes everything this contract needs on qovery_application: root path, Dockerfile path, deployment stage, and deployment restrictions. Write the contract once as a module and reuse it for every service, so staging and production come from the same definition.

Prove It Before You Migrate the Second Service

The rollout starts with a single service that imports shared packages and owns migrations. Before moving anything else, four change tests confirm that selective deployment works: change the service, change a shared package, change a dev-only config, change the lockfile, and check that Qovery triggers exactly the services the dependency graph predicts.

Follow the Full Tutorial

The full tutorial is in the Qovery documentation, with the Dockerfile, the Terraform module, the deployment restriction lists, the pipeline layout, and the five-phase rollout plan:

Run a Microservices Monorepo Without Rebuilding Everything →