Automating the creation of Applications at scale with ApplicationSet: seven generator types, dynamic templates, and real use cases from multi-cluster to PR preview environments.

In episode 10 we learned to restrict access with ArgoCD Projects. But there's a practical problem we haven't touched: creating the Application itself is still manual. For 3 applications that's fine; for 10 clusters × 5 teams × 4 applications — that's 200 Applications to write, maintain, and delete. Not realistic. In this episode we discuss ApplicationSet — an ArgoCD resource that defines an Application template and a generator engine that explodes it into dozens or hundreds of Applications automatically.
Why does this matter? ApplicationSet is ArgoCD's answer to scale. With a single YAML file, you can roll applications out to all clusters at once, promote environments by changing one line, or create a preview environment for every pull request. This is the feature that separates a "demo" setup from an "enterprise" setup.
Without ApplicationSet, we face three problems:
ApplicationSet answers with a single abstraction: a template (the Application shape) + a generator (the parameter source that determines how many Applications are produced and what they look like).
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
namespace: argocd
spec:
goTemplate: true
generators:
- list:
elements:
- cluster: dev
url: https://kubernetes.default.svc
- cluster: prod
url: https://eks-prod.example.com
template:
metadata:
name: guestbook-{{.cluster}}
spec:
project: default
source:
repoURL: https://github.com/argoproj/argocd-example-apps.git
path: guestbook
destination:
server: '{{.url}}'
namespace: guestbookgenerators defines the set of parameters. Here, list produces two elements: the dev and prod clusters.template is the Application skeleton; values like the cluster and url parameters are filled in from the generator.guestbook-dev, guestbook-prod) are fully managed by the ApplicationSet controller — if parameters change, the Application is updated too.Note
ApplicationSet supports two templating modes: default fasttemplate (using cluster without a dot) and Go template (goTemplate: true, using cluster with a leading dot). Go templates are more flexible for conditional logic — use it from the start so you don't need to migrate.
ApplicationSet provides seven generator types:
| Generator | Parameter source | Typical use case |
|---|---|---|
| List | Static element list | Small, known combinations |
| Cluster | Clusters registered in ArgoCD | Deploy to all clusters |
| Git (files) | Contents of JSON/YAML files in a repo | Per-tenant configuration |
| Git (directories) | Repo subdirectories | Monorepo, an app per folder |
| Matrix | Cartesian product of two generators | Cluster × environment combinations |
| Merge | Combined generator parameters | Override values per cluster |
| SCM Provider | Repos from a GitHub/GitLab org | Auto-discover application repos |
| Pull Request | Open PRs/merge requests | PR preview environments |
The simplest — exactly like the example above: a static list of elements, each becoming one Application.
Reads the clusters registered in ArgoCD (from episode 9) and produces an Application for every cluster matching the label selector:
spec:
generators:
- cluster:
selector:
matchLabels:
env: prod
template:
metadata:
name: '{{.name}}-guestbook'
spec:
source:
repoURL: https://github.com/devnull/gitops-repo.git
path: guestbook
destination:
server: '{{.server}}'
namespace: guestbookThe name parameter comes from the cluster name, server from the API address, and cluster labels can be accessed through the metadata.labels field. Adding a new cluster labeled env=prod immediately creates a new Application automatically — without changing anything.
Reads the Git repository structure:
path and path.basename parameters.tenant-a.json file, and ArgoCD produces an Application for tenant-a.spec:
generators:
- git:
repoURL: https://github.com/devnull/gitops-repo.git
revision: main
directories:
- path: apps/*
template:
metadata:
name: '{{.path.basename}}'
spec:
source:
repoURL: https://github.com/devnull/gitops-repo.git
path: '{{.path}}'cluster x environment combinations. Two generators inside one matrix produce the combination of all parameters.spec:
generators:
- pullRequest:
github:
owner: devnull
repo: billing-api
labels: [preview]
template:
metadata:
name: 'billing-pr-{{.number}}'
spec:
source:
repoURL: https://github.com/devnull/billing-api.git
path: manifests/overlays/preview
targetRevision: '{{.head_sha}}'
destination:
namespace: 'billing-preview-{{.number}}'env=prod.apps/* folder.targetRevision value per environment in the matrix generator: dev uses the dev branch, prod uses the v1.2.3 tag.Every template field can be filled with generator parameters — name, path, namespace, even project. Labels and annotations written in template.metadata propagate to the generated Applications, so they can be used for UI filtering and integration with other tools (e.g. per-application monitoring tags). If you want labels generated from parameters, use templating on the label values too.
goTemplate: true. Go template syntax (parameters with a leading dot, like cluster) is only valid when Go templates are enabled; without that flag, use dot-less notation. Inconsistency between the two often leaves manifests ungenerated.argocd app list, then remove them by changing the generator or deleting the ApplicationSet.matchLabels means all clusters — including experimental ones. Always use explicit labels.maxResources or limit the number of allowed PRs.This episode opened up the power of ApplicationSet: the template-plus-generator structure, the seven generator types (list, cluster, git files/directories, matrix, merge, SCM provider, pull request), use cases from multi-cluster to PR preview, and how parameters replace parts of the Application template.
The points you should take with you:
All these applications are still defined as manifests stored in Git — and that's where the classic GitOps problem arises: what about secrets? In the next episode 12 we discuss Secrets Management: a comparison of Sealed Secrets, External Secrets Operator, and SOPS, plus best practices for encryption, rotation, and RBAC for secrets. See you in episode 12!