Nov 17, live webinar: ECS to EKS without freezing the roadmap for a quarter

Argo CD PR Generator vs a Managed Platform for Kubernetes Preview Environments: the Full Build Sheet

The Argo CD ApplicationSet pull request generator gives you about 40 lines of YAML per preview. This build sheet shows the real YAML for it and for everything you still own around it (image builds, a database per PR, secrets, DNS and TLS, PR comments, cleanup and cost caps), what breaks after a month, and when a managed platform is the better trade.

Alessandro Carrano
Head of Product
NOV 14, 2026 · 18 MIN
Argo CD PR Generator vs a Managed Platform for Kubernetes Preview Environments: the Full Build Sheet

Key points:

  • The Argo CD ApplicationSet pull request generator turns each open PR into an Argo CD Application on GitHub, GitLab, Gitea, Bitbucket Server, Bitbucket Cloud or Azure DevOps, and deletes it when the PR closes or stops matching. It polls every 30 minutes by default unless you expose the ApplicationSet webhook server, which needs its own Ingress.
  • The generator deploys manifests at a commit. A usable preview needs seven more components: an image build gate, a database per PR, secrets, wildcard DNS and TLS, the URL posted on the PR, cleanup of what Argo CD leaves behind, and cost caps. Each one has a failure mode that shows up around day 30.
  • Three things leak by default: PersistentVolumeClaims from StatefulSets (Kubernetes keeps them unless you change persistentVolumeClaimRetentionPolicy), namespaces you did not declare as manifests, and previews for PRs that stay open for weeks.
  • Keep the PR generator when your stack is already Helm or Kustomize, Git must stay the only source of truth, and a platform engineer owns the glue. Pick a managed platform when nobody wants to own that glue, previews need real databases and per-PR secrets, or coding agents open PRs faster than humans clean them up.
  • Qovery is the managed option that runs in your own cloud account or on your existing cluster. It clones a blueprint environment per PR, builds images, provisions the database, posts the URL and deletes everything on merge. Its Argo CD integration can show your existing Argo CD applications next to the previews, so you do not have to migrate production to try it.

Qovery · Infrastructure control plane
A control plane for platform teams and their coding agents
Learn more

The Argo CD pull request generator is about 40 lines of YAML. A preview environment a reviewer trusts is closer to ten components, and the generator is one of them.

I have seen the same project play out in several platform teams: someone wires up an ApplicationSet with a pullRequest generator on a Friday, the first preview shows up on Monday, and then the next six weeks go into images that do not exist yet, databases that never get deleted, certificates that hit rate limits and namespaces nobody remembers creating. Argo CD did its job the whole time; the rest is the size of the problem.

We already wrote a short comparison of Argo CD and Qovery Free for agent PR environments. This article is the build sheet behind it: the real YAML for the generator, the real YAML for each piece you still own, what breaks after a month, and a fair way to decide between building it and using a managed platform.

What does the Argo CD ApplicationSet pull request generator actually do?

The pull request generator lists open pull requests through your Git provider's API and renders one Argo CD Application per PR from a template. When a PR closes or no longer matches your filters, the Application is removed, and by default Argo CD deletes the resources it deployed.

Here is what the official generator docs give you to work with:

  • Providers: GitHub, GitLab, Gitea, Bitbucket Server, Bitbucket Cloud and Azure DevOps.
  • Template parameters: number, title, branch, branch_slug (DNS-safe, cut to 50 characters), target_branch, target_branch_slug, head_sha, head_short_sha (8 characters), head_short_sha_7, labels (Go templates only) and author.
  • Filters: branchMatch, targetBranchMatch and titleMatch regular expressions, plus label filtering on GitHub and GitLab. A PR must carry all listed labels to match.
  • Polling: the controller checks every requeueAfterSeconds, which defaults to 1800 seconds. That is a 30-minute wait between "PR opened" and "preview exists" unless you set up the webhook.
  • Deletion: Applications generated by an ApplicationSet carry the resources-finalizer.argocd.argoproj.io finalizer, so their Kubernetes resources are deleted with them, unless you set preserveResourcesOnDeletion: true (Application deletion docs).

Here is the ApplicationSet I would start from in November 2026. It authenticates as a GitHub App rather than a personal token, only picks up PRs that carry a preview label, and pins everything to the PR's head commit:

YAML
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: shop-previews
  namespace: argocd
spec:
  goTemplate: true
  goTemplateOptions: ["missingkey=error"]
  generators:
  - pullRequest:
      github:
        owner: acme
        repo: shop
        appSecretName: github-app-repo-creds   # GitHub App, not a PAT
        labels:
        - preview                              # set by CI once images exist
      filters:
      - targetBranchMatch: "^main$"
      requeueAfterSeconds: 600                 # safety net; the webhook does the real work
  template:
    metadata:
      name: 'shop-pr-{{.number}}'
      labels:
        preview: "true"
        pr: '{{.number}}'
    spec:
      project: previews                        # never templated, see Security below
      source:
        repoURL: https://github.com/acme/shop.git
        targetRevision: '{{.head_sha}}'
        path: deploy/chart
        helm:
          releaseName: shop
          valuesObject:
            image:
              tag: 'pr-{{.number}}-{{.head_short_sha}}'
            ingress:
              host: 'pr-{{.number}}.preview.acme.dev'
            postgres:
              enabled: true                    # per-PR database, see below
      destination:
        server: https://kubernetes.default.svc
        namespace: 'shop-pr-{{.number}}'
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
        - CreateNamespace=true

Two details from the docs change how you deploy this.

The ApplicationSet webhook is separate from the Argo CD API webhook. The ApplicationSet controller runs its own webhook server, exposed as a ClusterIP Service, and the docs say you need "an ApplicationSet specific Ingress resource" to reach it. GitHub then sends opened, closed, reopened, labeled, unlabeled and synchronize events to /api/webhook. The Service is argocd-applicationset-controller on port 7000 in the upstream install manifest:

YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-applicationset-webhook
  namespace: argocd
spec:
  ingressClassName: nginx
  rules:
  - host: appset-webhook.acme.dev
    http:
      paths:
      - path: /api/webhook
        pathType: Prefix
        backend:
          service:
            name: argocd-applicationset-controller
            port:
              number: 7000

Only admins should create ApplicationSets. The ApplicationSet security docs warn that a templated project field in a PR-driven ApplicationSet can let a PR author grant themselves management of out-of-bounds resources. Hardcode project: previews and give that AppProject a destination limited to shop-pr-* namespaces.

The generator is well designed and free, and it is the smallest part of the work.

What do you still have to build around the PR generator?

You still own seven components: an image build gate, a database per PR, secrets, wildcard DNS and TLS, the PR comment with the URL, cleanup of what the finalizer does not catch, and cost guardrails. Each comes from a different open source project with its own upgrade cycle.

ComponentWhat it doesTypical toolWho owns it with the PR generatorDay-30 failure mode
Image build gateBuilds pr-<n>-<sha> before Argo CD syncsGitHub Actions, GitLab CI, BuildkiteYour CIPods in ImagePullBackOff when Argo CD syncs first
Database per PRIsolates schema migrations per previewCloudNativePG, a Postgres StatefulSet, a branching serviceYour chartOrphaned volumes that keep billing
SecretsSandbox API keys per previewExternal Secrets Operator, Sealed SecretsYour platform teamProduction keys copied into previews
DNS and TLSpr-123.preview.acme.dev with HTTPSingress-nginx, cert-manager, external-dnsYour platform teamLet's Encrypt rate limits with per-PR certificates
URL on the PRTells reviewers and agents where to clickArgo CD Notifications, a CI stepYour platform teamComments posted before the preview is healthy
CleanupRemoves what the finalizer leavesCronJob, Kyverno cleanup policies, scriptsYour platform teamStale previews for PRs open for weeks
Cost guardrailsCaps CPU, memory and nodes per previewResourceQuota, LimitRange, node pool limitsYour platform teamA load test in one PR starves the others

Here is each one with the YAML I would ship.

1. How do you stop Argo CD from deploying an image that does not exist yet?

Gate the preview on the build. The ApplicationSet above only matches PRs with the preview label, so CI adds that label after the image is pushed. Argo CD never sees a PR whose image is missing.

YAML|.github/workflows/preview-image.yml
name: preview-image
on:
  pull_request:
    types: [opened, synchronize, reopened]
permissions:
  contents: read
  packages: write
  pull-requests: write
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: docker/login-action@v3
      with:
        registry: ghcr.io
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}
    - name: Build and push
      run: |
        SHA=$(echo "${{ github.event.pull_request.head.sha }}" | cut -c1-8)
        TAG="pr-${{ github.event.number }}-${SHA}"
        docker build -t ghcr.io/acme/shop:${TAG} .
        docker push ghcr.io/acme/shop:${TAG}
    - name: Opt the PR into a preview
      env:
        GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: gh pr edit ${{ github.event.number }} --add-label preview --repo ${{ github.repository }}

The tag uses the first 8 characters of the head SHA, which matches the generator's head_short_sha. Get that wrong and every preview pulls a tag that was never built.

The label trick covers the first push. For later pushes the label is already there, so the webhook fires on synchronize and Argo CD can still race your build. In practice teams either accept a few minutes of ImagePullBackOff that heals itself, or remove the label at the start of the job and add it back at the end. Both work, and each has a cost.

2. How do you give every pull request its own database?

Ship the database in the chart, so it lives and dies with the preview namespace. With the CloudNativePG operator, a per-PR Postgres is one custom resource. The operator supports three bootstrap methods: initdb for an empty cluster, recovery from a base backup, and pg_basebackup to clone a live cluster of the same major version (CloudNativePG bootstrap docs).

YAML|deploy/chart/templates/postgres.yaml
{{- if .Values.postgres.enabled }}
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: shop-db
spec:
  instances: 1
  bootstrap:
    initdb:
      database: app
      owner: app
  storage:
    size: 2Gi
{{- end }}

The operator writes the application credentials to a Secret named shop-db-app, which your Deployment reads. Then you still need seed data that looks real without being copied from production, which is usually a migration plus a fixtures Job with an Argo CD PostSync hook.

Watch the volumes. If you go the plain StatefulSet route instead of an operator, Kubernetes keeps the PVCs when the StatefulSet is deleted. The StatefulSet docs are explicit: deleting or scaling down a StatefulSet "will not delete the volumes associated with the StatefulSet", and the default persistentVolumeClaimRetentionPolicy is Retain. Set it on every preview StatefulSet:

YAML
spec:
  persistentVolumeClaimRetentionPolicy:
    whenDeleted: Delete
    whenScaled: Retain

3. How do you inject secrets without copying production keys into previews?

Use one ExternalSecret per preview that reads from a dedicated sandbox path in your secret store. The External Secrets Operator syncs those values into a regular Kubernetes Secret in the PR namespace:

YAML|deploy/chart/templates/external-secret.yaml
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: shop-sandbox-keys
spec:
  refreshInterval: 1h
  secretStoreRef:
    kind: ClusterSecretStore
    name: aws-secrets-manager
  target:
    name: shop-sandbox-keys
  dataFrom:
  - extract:
      key: previews/shop          # sandbox keys only, never prod/shop

Policy is harder than the YAML. Someone has to decide which third-party sandboxes a preview may call (Stripe test mode, a staging OAuth client, a fake email provider), and how to stop anyone from pointing key: at the production path. On Argo CD, that is an AppProject restriction plus a code review habit, or a Kyverno policy that rejects ExternalSecret objects reading outside previews/.

4. How do you give every preview a URL with valid HTTPS?

Issue one wildcard certificate for *.preview.acme.dev and reuse it in every preview. Wildcards require the ACME DNS-01 challenge; Let's Encrypt states that HTTP-01 cannot issue wildcard certificates (challenge types).

YAML
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: preview-wildcard
  namespace: ingress-nginx
spec:
  secretName: preview-wildcard-tls
  dnsNames:
  - "*.preview.acme.dev"
  issuerRef:
    kind: ClusterIssuer
    name: letsencrypt-dns01

Set it as the ingress controller's default certificate, and add one wildcard DNS record pointing *.preview.acme.dev at the load balancer.

One certificate per preview runs into rate limits. Let's Encrypt allows "up to 50 certificates" per registered domain every 7 days, refilling one every 202 minutes (Let's Encrypt rate limits). A team whose coding agents open 15 PRs a day crosses that in four days, and then production renewals under the same domain compete for the same budget. Use a separate registered domain for previews, like acme-preview.dev, so a busy week never blocks a production certificate.

5. How does the preview URL get back to the pull request?

Use Argo CD Notifications with the GitHub service. Its pullRequestComment block upserts a comment identified by commentTag, so each new push edits the same comment instead of piling up new ones (GitHub service docs):

YAML|argocd-notifications-cm
data:
  service.github: |
    appID: <app-id>
    installationID: <installation-id>
    privateKey: $github-privateKey
  trigger.on-preview-healthy: |
    - when: app.status.health.status == 'Healthy' and app.status.sync.status == 'Synced'
      oncePer: app.status.sync.revision
      send: [preview-ready]
  template.preview-ready: |
    github:
      status:
        state: success
        label: "preview/{{.app.metadata.name}}"
        targetURL: "https://pr-{{index .app.metadata.labels "pr"}}.preview.acme.dev"
      pullRequestComment:
        content: |
          Preview is up: https://pr-{{index .app.metadata.labels "pr"}}.preview.acme.dev
          Commit {{.app.status.sync.revision}}
        commentTag: "preview/{{.app.metadata.name}}"

Subscribe the generated Applications by adding notifications.argoproj.io/subscribe.on-preview-healthy.github: "" to the template's annotations. The service finds the repository and commit from the Application's repoURL and synced revision by default, which works when the chart lives in the app repository, as it does here.

This is also where a coding agent finds out whether its change works. If the agent cannot read the preview's logs, it learns "something failed" and nothing else, unless you give it scoped access to the Argo CD API or to the preview namespaces.

6. What does the finalizer not clean up?

The finalizer deletes the resources Argo CD tracks. Three things fall outside that:

  • Namespaces created by CreateNamespace=true. Argo CD creates them, but it does not manage them as part of the Application by default; the sync options docs describe a tracking annotation you have to set yourself to opt in. Test what happens on your version, then either render a Namespace manifest in the chart or sweep empty shop-pr-* namespaces on a schedule.
  • Volumes with a Retain policy, covered above.
  • PRs that never close. A draft PR left open for six weeks keeps its preview running for six weeks. The generator does exactly what you asked.

A small CronJob handles the last case by removing the preview label from PRs with no push in 72 hours, which makes the generator delete the preview on the next webhook or poll:

YAML
apiVersion: batch/v1
kind: CronJob
metadata:
  name: preview-reaper
  namespace: argocd
spec:
  schedule: "0 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: Never
          containers:
          - name: reaper
            image: ghcr.io/cli/cli:latest   # pin a digest in production
            env:
            - name: GH_TOKEN
              valueFrom: { secretKeyRef: { name: reaper-gh-token, key: token } }
            command: ["/bin/sh", "-c"]
            args:
            - |
              CUTOFF=$(date -u -d '72 hours ago' +%Y-%m-%dT%H:%M:%SZ)
              gh pr list --repo acme/shop --label preview --json number,updatedAt \
                --jq ".[] | select(.updatedAt < \"$CUTOFF\") | .number" |
              xargs -r -I{} gh pr edit {} --repo acme/shop --remove-label preview

7. How do you stop previews from eating the cluster?

Put a ResourceQuota and a LimitRange in every preview namespace, through the chart, and cap the node group that runs previews:

YAML
apiVersion: v1
kind: ResourceQuota
metadata:
  name: preview-quota
spec:
  hard:
    requests.cpu: "2"
    requests.memory: 4Gi
    limits.memory: 6Gi
    persistentvolumeclaims: "2"
    requests.storage: 10Gi

The node group's maximum size is your real spending cap, because it bounds the worst case whatever your agents do. Our cost model for a preview per agent PR puts one full-stack preview at about $0.07 an hour on an existing EKS cluster in us-east-1, and shows that lifetime drives the bill more than size: at 30 agent PRs per working day, weekly manual cleanup costs about $7,700 a month, against about $95 with delete-on-merge, schedules, on-demand creation and Spot.

Preview environments per PR, without owning the glue.
Qovery clones a blueprint environment for every pull request on your own AWS, GCP, Azure or Scaleway account, or your existing Kubernetes cluster: images, database, secrets, URL on the PR, and deletion on merge. Keep Argo CD for production if you want.

What breaks after the first month?

These are the problems I see show up after a few weeks of real traffic, each with the limit behind it:

  • Git provider API budget. Every ApplicationSet with a PR generator lists PRs on each poll. A personal access token gets 5,000 requests per hour on GitHub, and GITHUB_TOKEN in Actions gets 1,000 per hour per repository (GitHub REST rate limits). Shorten requeueAfterSeconds across 40 repositories with one token and you will find the ceiling. Use a GitHub App and the webhook.
  • Certificate budget. Covered above: 50 certificates per registered domain per 7 days.
  • Argo CD upgrades. Argo CD ships a minor release every three months, and only the three most recent minor versions get patches (release process). v3.6.0 shipped on 3 November 2026 (release notes). Your preview pipeline now has a quarterly upgrade to test, alongside cert-manager, External Secrets and your database operator.
  • Schema drift. A migration in PR 1842 and a different one in PR 1845 are fine with a database per PR, and broken with a shared staging database. Teams that skip step 2 to save time find this out when two agents work on the same table.
  • Nobody owns it. The preview system touches CI, Argo CD, DNS, the secret store and the cluster. When it breaks at 6pm, it belongs to whoever built it.

How much does the DIY path really cost?

The software is free, so the cost is engineering time. I will not invent a benchmark for how long this takes, because it depends heavily on what you already run. Here is the worksheet I use with teams instead, with assumptions you replace with your own:

Line itemWhat drives itExample assumption to replace
Initial buildSeven components above, wired and tested3 to 6 engineer-weeks if ingress, cert-manager and a secret store already exist
UpgradesArgo CD every 3 months, plus cert-manager, ESO, the DB operator1 to 2 days a quarter
Break-fixRate limits, stuck finalizers, orphaned volumes, failing seedsA few hours a week once agents open PRs daily
New servicesEvery new service needs chart values, secrets and a DB decisionHalf a day each
Cloud spendPreview compute and storageYour node group cap, see the cost model above

Multiply engineer-weeks by your own fully loaded cost and compare it with the license of whatever you would buy. If you already have a platform team that builds this kind of thing for fun, the DIY path is often cheaper. If the person who would build it is also your only SRE, it usually is not.

Argo CD PR generator vs a managed platform: how do they compare?

A managed preview platform owns the seven components above as product features; the PR generator owns one and leaves the rest to you. The trade is control and zero license cost against weeks of platform work and a permanent maintenance line.

CapabilityArgo CD PR generator (DIY)Qovery (managed, runs in your account)
LicenseOpen source, Apache 2.0Free plan, then paid plans (pricing)
Where previews runAny Kubernetes cluster you runYour own AWS, GCP, Azure or Scaleway account, or an existing cluster (EKS, GKE, AKS, k3s, on-premise)
Preview definitionHelm chart or Kustomize in GitA blueprint environment (Console, CLI, Terraform provider)
TriggerWebhook or 30-minute poll, filtered by labels and regexEvery PR on the blueprint's base branch, or on demand with a PR comment
Image build per commitYour CIBuilt by Qovery from the PR branch
Database per PRYour chart or operatorContainer database cloned per preview, or shared
SecretsExternal Secrets or Sealed Secrets, your policyVariables and secrets cloned from the blueprint
DNS and TLSYour ingress, cert-manager, DNS recordsURL per preview, ingress and certificates handled
URL on the PRArgo CD Notifications or a CI stepPosted on the PR
CleanupFinalizer, plus your sweeps for namespaces, volumes, stale PRsEnvironment deleted on merge or close
Schedules and cost capsCronJobs, quotas, node group limitsDeployment rules to stop previews on a schedule, plus your node group limits
Access for coding agentsGit only, unless you grant Argo CD API or cluster accessMCP Server (read-only by default), CLI, Agent Skills, OPA-based API policy tokens
AuditGit history, Argo CD events, Kubernetes audit logsQovery audit logs plus Git history

Qovery is not the only managed option. Bunnyshell and Northflank also build full preview environments from PRs, and Signadot takes a different approach with request-routed sandboxes that share a baseline cluster instead of cloning the whole stack. Our comparison of 8 per-PR environment tools on Kubernetes covers them side by side, including Flux, vCluster, Helm and Kustomize.

When should you keep the Argo CD PR generator?

Keep it when you already have most of the surrounding pieces and someone owns them. Concretely, when most of these are true:

  • Your services are already packaged as Helm charts or Kustomize, and previews must render exactly what production renders.
  • Git must be the only source of truth for anything that reaches a cluster, for audit or for culture.
  • ingress, cert-manager, a secret store and a database operator already run in the cluster for other reasons, so the marginal cost is wiring them together.
  • A platform engineer owns preview environments as a product, with time set aside for upgrades.
  • You want no vendor in the loop at any price.

In that situation the PR generator is the right tool, and the YAML above is most of what you need.

When is a managed platform the better trade?

A managed platform wins when the surrounding glue costs you more than the deployment itself. That is usually the case when:

  • Nobody wants to own the seven components. The team wants previews and has no appetite for running a preview system.
  • Previews need real databases and per-PR secrets from day one, because PRs change schemas.
  • Coding agents open PRs faster than humans close them. Claude Code, Cursor and Codex each end tasks with a PR, and every PR is a preview to create, update and delete.
  • Agents should debug their own previews. Reading logs and redeploying after a fix needs scoped access, which is hard to grant safely through raw cluster credentials.
  • The stack is not packaged as charts yet. A few services with Dockerfiles become a blueprint without writing Kubernetes YAML first.

This is where Qovery fits. Qovery is an Agentic DevOps platform: the control plane is Qovery's, and every preview runs on Kubernetes in your own cloud account or on the cluster you already run. You describe the stack once as a blueprint environment, turn on preview environments, and each PR gets a clone with its images built from the PR branch, its database, its variables and secrets, and a URL on the PR. Merge or close deletes it. Deployment rules stop previews outside working hours.

For agents, the MCP Server is read-only by default, and an API Policy Token attaches an Open Policy Agent policy evaluated on every request, so an agent can read logs and redeploy previews in one project and nothing else. Its actions show up in the audit log as policy:<token-id>:<token-name>. The feature is still in preview and its policy input contract may change, so check the docs before you build on it.

Can you keep Argo CD for production and use a managed platform for previews?

Yes, and for many teams that is the sensible split. Production keeps its charts, its reviews and its Argo CD audit story; previews move to a system built for short-lived environments.

Qovery's Argo CD integration connects an Argo CD instance running on a cluster added to Qovery. Your Argo CD applications appear as Qovery environments organized by namespace, with pod status, logs, shell access, sync and health status, and a manifest view. They stay read-only in Qovery: configuration and manifests stay in Git. The docs note that sync and rollback actions are planned and that behaviour may change, so treat it as a single view rather than a second deployment path today.

If you are weighing Argo CD itself, not just previews, our guide to Argo CD alternatives and managed GitOps control planes covers Akuity, Codefresh, Flux, Harness and others with who runs what.

How do I set up preview environments with Qovery from Claude Code or Cursor?

Install the Qovery Agent Skills, connect the MCP Server, then ask your agent in plain language. These are the only commands you need:

BASH|1. Agent Skills: one install for Claude Code, Cursor, Codex, OpenCode, Gemini CLI
curl -fsSL https://skill.qovery.com/install.sh | bash

# 2. MCP Server for Claude Code: OAuth sign-in, read-only by default
claude mcp add --transport http qovery https://mcp.qovery.com/mcp --callback-port 4242
  • Step 1 installs the skills, including qovery-onboard, qovery-deploy and qovery-preview. Nothing touches your cloud until you approve an action.
  • Step 2 opens a browser for you to sign in with OAuth. The server can read environments, logs and deployment status, but cannot change anything.
  • Then ask: "Use Qovery to set up preview environments for this repository on my cluster, with a Postgres per pull request." The qovery-preview skill detects or creates the blueprint environment and enables previews; you approve each step.

Only if you want the agent to redeploy previews itself, add the write-enabled MCP Server (this also requires write access to be enabled in the Qovery Console):

BASH
claude mcp add --transport http qovery "https://mcp.qovery.com/mcp?read_write=true" --callback-port 4242

More detail on the AI agent quickstart and the Claude Code integration page.

Frequently asked questions
Is the Argo CD ApplicationSet pull request generator enough for Kubernetes preview environments?

It is enough to deploy manifests per pull request and delete them when the PR closes. It is not enough for a preview a reviewer can use: you still build images per commit, a database per PR, secrets, wildcard DNS and TLS, the PR comment with the URL, cleanup of namespaces, volumes and stale PRs, and cost caps.

Argo CD ApplicationSet pull request generator vs a managed platform: which should I choose?

Choose the PR generator when your stack is already Helm or Kustomize, Git must be the only source of truth, and a platform engineer owns the surrounding components. Choose a managed platform such as Qovery when nobody wants to own that glue, previews need real databases and secrets per PR, or coding agents open PRs faster than humans clean them up.

How often does the Argo CD pull request generator check for new PRs?

Every 30 minutes by default, through requeueAfterSeconds: 1800. To create previews within seconds, expose the ApplicationSet controller's own webhook server through a dedicated Ingress (Service argocd-applicationset-controller, port 7000, path /api/webhook) and send pull request events from your Git provider.

Does Argo CD delete preview resources when the pull request is closed?

Yes for resources it tracks: generated Applications carry the resources-finalizer.argocd.argoproj.io finalizer unless you set preserveResourcesOnDeletion. Check three things separately: namespaces created through CreateNamespace=true, StatefulSet volumes (Kubernetes keeps them by default), and PRs that stay open for weeks.

Can I use Qovery for preview environments and keep Argo CD for production?

Yes. Qovery runs previews in your own cloud account or on your existing cluster, and its Argo CD integration shows your Argo CD applications as read-only Qovery environments, with logs, pod status and sync status, while deployments stay in Argo CD and Git.

Alessandro Carrano
About the author
Alessandro Carrano

Alessandro leads product at Qovery. He drives the changelog, roadmap, and product strategy - turning customer feedback into platform capabilities.

Next step

Preview environments per PR, without owning the glue.

Qovery clones a blueprint environment for every pull request on your own AWS, GCP, Azure or Scaleway account, or your existing Kubernetes cluster: images, database, secrets, URL on the PR, and deletion on merge. Keep Argo CD for production if you want.