Automated Preview Environments on Kubernetes: Deploy Every PR in Minutes

Developers spend hours waiting for deployments, and testers check the wrong version — staging can't handle parallel PRs. We set up automatic deployment of preview environments in Kubernetes: each PR gets an isolated space that lives only during review. Our team delivers the project turnkey — from pipeline setup to support, ensuring reliable operation and scaling with your business.

Our competencies:

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1365
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1330
  • B2B Advance company logo design
    B2B Advance company logo design
    776
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1077
  • AIDER company logo development
    AIDER company logo development
    1022
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1113

Imagine: a developer opens a PR with changes to an order form. QA waits for a link to test. The designer wants to see the button in context. The tech lead can't merge without a live review. Without preview environments, everyone waits for a deploy to staging, which someone else already occupies with another branch. In a typical team of 10 developers, each PR waits an average of 2 hours for a staging deploy. With preview environments, deployment takes 3 minutes. Our team of DevOps engineers has 7+ years of experience in CI/CD and Kubernetes. We've deployed preview environments for dozens of projects—from startups to enterprise. We'll help you automate PR testing. Get a project evaluation—just contact us.

Preview environments solve this bottleneck: each PR gets an isolated environment automatically, lives as long as the PR is open, and dies after merge or close. This reduces review time by 40%, cuts cloud infrastructure costs by 30% thanks to auto‑cleanup, and eliminates resource conflicts. Below, we break down how to build the system on Kubernetes and GitHub Actions, and which pitfalls to avoid.

Why Staging Doesn't Work for Parallel PRs

One staging environment for multiple active PRs is a classic problem. The feature/checkout-v2 branch overwrites bugfix/payment-redirect, the tester checks the wrong thing, the developer doesn't understand where the bug came from. Staging becomes a permanent resource conflict.

The second issue is dependencies. If the application uses a database, Redis, S3—each PR needs an isolated copy of those services, or at least a separate schema/namespace. Without that, tests from one PR corrupt data from another.

The third is lifetime. Stale PRs pile up, environments are not cleaned, and the cloud bill grows. Automatic cleanup on closed or merged events is essential.

How to Deploy Preview Environments on Kubernetes

A typical implementation on Kubernetes + GitHub Actions: when a PR is opened, a workflow is triggered that builds the image, pushes it to the registry with tag pr-{number}, applies a Helm chart in the namespace preview-pr-{number}, and comments on the PR with a link to the environment.

Example workflow
---
# .github/workflows/preview.yml (fragment)
on: pull_request:
  types: [opened, synchronize, reopened, closed]
jobs:
  deploy-preview:
    if: github.event.action != 'closed'
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to preview namespace
        run: |
          helm upgrade --install \
            preview-pr-${{ github.event.number }} ./helm/app \
            --namespace preview-pr-${{ github.event.number }} \
            --create-namespace \
            --set image.tag=pr-${{ github.event.number }} \
            --set ingress.host=pr-${{ github.event.number }}.preview.example.com
  cleanup-preview:
    if: github.event.action == 'closed'
    runs-on: ubuntu-latest
    steps:
      - name: Delete preview namespace
        run: kubectl delete namespace preview-pr-${{ github.event.number }} --ignore-not-found

For databases, there are several approaches. The cheapest is a separate PostgreSQL schema per PR: CREATE SCHEMA pr_519 AUTHORIZATION app_user;, migrations are applied, the schema is dropped after merge. No separate database pods needed. This works if the application supports search_path.

If full isolation is needed—ephemeral database via an operator (e.g., CloudNativePG with cluster templates) or Neon/PlanetScale with branch per PR.

DNS and Ingress

A wildcard certificate for *.preview.example.com plus a single wildcard Ingress rule via nginx-ingress or Traefik:

---
# ingress wildcard rule
- host: "*.preview.example.com"
  http:
    paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: preview-router # routes by hostname to the correct service

Alternatively, cert-manager with Let's Encrypt DNS‑01 challenge issues the wildcard automatically.

Alternatives to Kubernetes

If you don't have a cluster, Render, Railway, and Fly.io natively support preview environments. Vercel and Netlify do it out of the box for static sites and Next.js. For heavier applications, Uffizzi or Namespace (formerly Shipyard) deploy environments in ephemeral clusters without you managing infrastructure.

A Docker Compose‑based approach: each PR runs docker compose up on a dedicated runner with port forwarding via Cloudflare Tunnel or ngrok. Cheap, but doesn't scale beyond ~10 concurrent PRs.

How to Avoid Database Conflicts in Preview

The most reliable method is to use separate PostgreSQL schemas for each PR. The application should dynamically select a schema via the environment variable SEARCH_PATH. This provides data isolation without spinning up additional containers. An alternative is ephemeral databases based on CloudNativePG: each PR gets a mini‑cluster that lives exactly as long as the namespace. This approach is more expensive but offers full instance‑level isolation.

What's Included in Setting Up Preview Environments?

We provide a complete turnkey package:

  • Audit of your current infrastructure and CI/CD pipelines.
  • Architecture design: database isolation strategy, DNS scheme, TTL policy.
  • Implementation of Helm charts or Kustomize overlays for preview environments.
  • Configuration of GitHub Actions / GitLab CI workflows with automatic deployment and cleanup.
  • Integration of wildcard Ingress and TLS via cert-manager.
  • Testing: simultaneously open 5 PRs, verify data isolation and cleanup.
  • Documentation: runbook for on‑call, description for adding new dependencies.
  • Team training and post‑deployment support.

Comparison of database isolation strategies:

Strategy Isolation Cost Complexity
Separate PostgreSQL schema Medium Low Low
Ephemeral database (CloudNativePG) High Medium Medium
External service (Neon/PlanetScale) High High Low

Timeline Guidelines

Scenario Duration
Static site / SPA (Vercel/Netlify) 0.5–1 day
Monolith without DB, Docker Compose 1–2 days
Service with PostgreSQL, Kubernetes 3–5 days
Microservices, multiple dependencies 1–2 weeks

Pricing is determined after an audit: we need to understand your current CI/CD stack and infrastructure. The investment pays for itself through faster development—review time drops from 2 days to 4 hours.

Common Pitfalls and How to Avoid Them

Without automatic cleanup, dozens of dead namespaces accumulate in a month, increasing the cloud bill. Solution: set a TTL or cleanup on PR close event. A shared database without isolation leads to migration conflicts—schema‑per‑preview helps. Using production secrets in preview environments is unacceptable: a separate secrets store is needed. Without resource limits, one active PR can consume the whole node; 100m CPU and 256Mi memory suffice for preview. These measures ensure stability and cost savings.

Ready to implement preview environments? Get a consultation on your CI/CD—we'll analyze your current infrastructure and choose the best strategy. Contact us for an audit and project evaluation.