Preview environments for a microservice architecture with 10+ repositories.

Blog / Preview environments

A practical GitOps model for single-service and coordinated preview environments across ten or more repositories.

Hand-drawn multi-repository preview flow connecting service repositories, a shared environment definition, GitOps and an isolated Kubernetes stack

We have seen multi-repository previews fail in a familiar way: each service builds correctly, but nobody can say which versions are running together. The fix starts with a small environment definition that records the baseline, changed services, data rules and cleanup time.

A branch name is a weak link across many repositories. The branch may exist in only some repositories, and the same name may point to unrelated work in another service.

When one pull request changes, most services can use exact versions from a known-good baseline. A change across several services needs the exact commit for each service taking part. Both paths should produce the same environment definition.

One pull request shows one part

Record the complete set of service versions for every preview.

In a monorepo, one commit can identify the whole application. Across many repositories, each service has its own history. A branch may exist in only some repositories and may point to unrelated work in others.

We use a version map for the preview. The changed service uses its pull-request commit. Every other service keeps the exact version from a known-good staging or release baseline. This makes the preview repeatable and shows reviewers what is running.

01

Baseline

A known-good environment supplies exact versions for services outside the change.

02

Changed services

One or more repository commits replace baseline versions for this preview.

03

Environment rules

Namespace, data, secrets, DNS, resource limits and cleanup time stay with the version map.

Use the smallest stack that answers the review

Support quick service reviews and coordinated changes through one workflow.

Most changes affect one service. Build the candidate version for that service and combine it with baseline versions for the rest of the stack. This path keeps setup fast.

Changes across APIs, workers, identity or shared contracts need a coordination pull request that lists the exact commits taking part. After that, both paths use the same environment definition, naming, GitOps deployment, status and cleanup.

01

Single-service preview

One repository label selects its candidate image. All other services use the baseline.

02

Coordinated preview

A control pull request selects several repository commits for a shared contract or workflow change.

03

Shared workflow

Both modes use the same naming, namespaces, charts, rules, status and cleanup.

One small file

Keep the environment definition in a separate GitOps or automation repository.

We have found that a separate repository makes ownership clearer. Service workflows publish images. The automation repository records the combination that reviewers asked for. Argo CD reads that reviewed state.

01

Preview identity

A unique ID, owner, source pull requests and current status.

02

Service versions

Repository, commit, exact image reference and optional Helm values for every changed service.

03

Baseline

The staging or release version used for unchanged services.

04

Dependencies

Data services, identity, queues, external test services and migration rules.

05

Platform limits

Target cluster, namespace, DNS suffix, resource limits, network rules and Argo CD project.

06

Cleanup

Creation time, maximum lifetime, last activity and deletion status.

Many repositories, one control path

Let service repositories build their images and let GitOps deploy the set.

Each service workflow builds and reports its own fixed image. The automation workflow adds those image references to the environment definition. Argo CD reads the definition, creates the applications and reports their health.

Multi-repository lifecycle
One preview ID connects every service decision

The automation repository records the service versions. GitOps creates the environment and sends the results back.

  1. 01
    Repository signal

    A service label or coordination pull request requests a preview.

  2. 02
    Build changed services

    The repositories taking part publish fixed images and test results.

  3. 03
    Record the version map

    The automation repository combines changed services with the selected baseline.

  4. 04
    Create applications

    ApplicationSets create the platform, dependency and workload applications.

  5. 05
    Apply in order

    Namespaces, secrets, data, identity and services become healthy in controlled steps.

  6. 06
    Report and remove

    One status updates the source pull requests. Closure or the time limit removes the stack.

Narrow access and clear limits

Limit where ApplicationSets can read from and deploy.

ApplicationSets can create applications from Git files, pull requests or a combination of inputs. Keep those inputs in approved repositories and use an AppProject that lists the allowed repositories, clusters, namespaces and resource types.

Some resources must be ready before others. Use sync waves or clear dependencies so secrets, databases and migrations are healthy before workloads start. Test database and cloud-resource deletion separately, since Kubernetes cleanup can leave them behind.

  • Keep ApplicationSet creation and project templates under platform-team control.
  • Use credentials for each repository instead of one token with write access to every service.
  • Limit preview destinations to a known namespace pattern and approved clusters.
  • Use fixed, trusted versions of charts, shared workflows and images.
  • Decide how databases, buckets and external resources will be deleted.

Copy only what the review needs

Choose which dependencies are separate for each preview.

A ten-service stack may also use identity, PostgreSQL, cache, messaging, object storage and external services. Copying every managed service for every pull request quickly becomes slow and expensive.

We usually separate a database schema, bucket or queue when state or migrations are part of the review. Stable identity and external test services can remain shared when reviewers can see that limit.

01

Separate for each preview

Use temporary schemas, databases, buckets or queues when state and migrations are part of the change.

02

Shared test service

Reuse stable services when a separate copy adds cost without improving the review.

03

Test replacement

Replace expensive or unsafe external systems with a sandbox, and show the limit to reviewers.

04

Preview-specific configuration

Use the same preview ID for secrets, service discovery, callbacks and events.

One result across many builds

Combine build, deployment and test results into one preview status.

A successful service build tells us that one image exists. The reviewer needs to know whether every required build finished, GitOps applied the changes, dependencies are healthy, migrations passed and the full test completed. Show partial failures instead of returning a URL that only partly works.

Use one preview ID in logs, metrics, DNS, namespace labels, GitOps applications and pull-request comments. The same ID lets cleanup find every part of the environment.

  • Report the exact service versions that are running alongside Argo CD health.
  • Stop older candidate builds when one of the participating branches changes.
  • Set a limit on active stacks, namespace quotas and workload defaults.
  • Remove inactive environment definitions even when one source pull request remains open.
  • Check that cleanup removes external DNS, data branches, secrets and cloud resources as well as Kubernetes objects.

Add coordination after cleanup works

Start with one changed service against a known baseline.

Prove the single-service path first: build one candidate, use baseline versions for every other service, create the namespace, return the results and delete everything.

We have seen teams add multi-service coordination too early and spend time debugging version-map logic before cleanup is reliable. Add the coordination repository when a real cross-service change needs it.

01

Phase one

One changed service, one baseline, one cluster and one automatic cleanup path.

02

Phase two

Several changed services, shared workflows and a clear data approach for each dependency.

03

Phase three

Capacity limits, several clusters and improvements based on real usage.

The practical outcome

Multi-repository previews work when every service version is clear.

The platform needs one reviewed environment definition, shared build rules and a GitOps controller with limited access. Every service repository can use the same workflow.

With that setup, a reviewer can answer three questions: which version of each service is running, which dependencies are shared, and when the stack will be removed.

References and related resources

Read the implementation details.

Make composition visible

Give every preview one version map and one cleanup path.

We can design the automation repository, baseline, service-version rules, shared builds, ApplicationSets, dependency approach, status and cleanup around your current microservice platform.

Schedule a platform call