# Argo CD Custom Resource Definitions (CRDs): A Complete Technical Guide

> Master Argo CD custom resource definitions (CRDs) with this technical guide. Understand how applications, appprojects, applicationsets, and more drive GitOps workflows via Kubernetes APIs.

- Repository: [Argo Project/argo-cd](https://github.com/argoproj/argo-cd)
- Tags: deep-dive
- Published: 2026-07-15

---

**Argo CD uses five primary Custom Resource Definitions—`applications`, `appprojects`, `applicationsets`, `argocdconfigs`, and `argocdnotifications`—to declaratively manage GitOps workflows through Kubernetes-native APIs.**

Argo CD custom resource definitions (CRDs) extend the Kubernetes control plane to support GitOps operations, allowing you to define applications, projects, and configuration generators as native resources. The `argoproj/argo-cd` repository ships these CRDs as YAML manifests that install into your cluster, enabling the application controller to watch and reconcile these objects alongside standard Kubernetes workloads. Understanding how these CRDs function internally—from the API definitions in `manifests/crds/` to the synchronization logic in the gitops-engine—is essential for troubleshooting sync failures and designing complex deployment pipelines.

## Core Argo CD CRDs and Their Purpose

Argo CD exposes its domain-specific objects through the Kubernetes API server using CRDs defined in the `manifests/crds/` directory. These definitions map Go structs to OpenAPI v3 schemas, enabling validation and storage by etcd.

### Application CRD (`applications.argoproj.io`)

The **Application** CRD represents the fundamental GitOps unit. Defined in [`manifests/crds/application-crd.yaml`](https://github.com/argoproj/argo-cd/blob/main/manifests/crds/application-crd.yaml), this resource specifies source repositories, target clusters, deployment paths, and sync policies. The application controller watches these resources to trigger deployments when Git state diverges from cluster state.

### AppProject CRD (`appprojects.argoproj.io`)

**AppProjects** group applications and enforce boundaries for RBAC, allowed source repositories, destination clusters, and sync windows. The definition resides in [`manifests/crds/appproject-crd.yaml`](https://github.com/argoproj/argo-cd/blob/main/manifests/crds/appproject-crd.yaml), implementing multi-tenancy controls that restrict where applications can deploy and what resources they can manage.

### ApplicationSet CRD (`applicationsets.argoproj.io`)

The **ApplicationSet** controller uses the CRD defined in [`manifests/crds/applicationset-crd.yaml`](https://github.com/argoproj/argo-cd/blob/main/manifests/crds/applicationset-crd.yaml) to generate multiple Application objects from templates. It supports generators for Git directories, cluster lists, SCM providers, and pull requests, enabling automated Application provisioning for microservices architectures.

### Configuration and Notification CRDs

**ArgoCDConfigs** (`argocdconfigs.argoproj.io`) store server configuration including Dex, OIDC, and RBAC policies in [`manifests/crds/argocdconfig-crd.yaml`](https://github.com/argoproj/argo-cd/blob/main/manifests/crds/argocdconfig-crd.yaml). **ArgoCDNotifications** (`argocdnotifications.argoproj.io`) manage notification subscriptions and triggers, defined in [`resource_customizations/notifications.argoproj.io/NotificationCRD.yaml`](https://github.com/argoproj/argo-cd/blob/main/resource_customizations/notifications.argoproj.io/NotificationCRD.yaml).

## How Argo CD Watches and Syncs CRDs

The Argo CD control plane uses dynamic clients and informers to monitor CRD state changes and orchestrate synchronization order.

### Dynamic Client Registration

The server component creates dynamic Kubernetes clients for each CRD using `extensionsclientset.ApiextensionsV1().CustomResourceDefinitions()`. In [`gitops-engine/pkg/sync/sync_context.go`](https://github.com/argoproj/argo-cd/blob/main/gitops-engine/pkg/sync/sync_context.go) around line 1290, the controller fetches CRD definitions:

```go
crd, err := sc.extensionsclientset.ApiextensionsV1().
        CustomResourceDefinitions().
        Get(ctx, name, metav1.GetOptions{})

```

These informers feed resource events into the application controller's reconciliation loop.

### Task Ordering for CRD Dependencies

When an Application includes CRDs in its manifest set, Argo CD must apply them before dependent custom resources. The **task ordering logic** in [`gitops-engine/pkg/sync/sync_tasks.go`](https://github.com/argoproj/argo-cd/blob/main/gitops-engine/pkg/sync/sync_tasks.go) (around line 41) classifies resources by kind, ensuring CRDs precede their instances in the synchronization wave. This prevents "resource not found" errors when applying Custom Resources whose definitions haven't reached the `Established` state.

### Application Controller Reconciliation

The application controller ([`controller/sync.go`](https://github.com/argoproj/argo-cd/blob/main/controller/sync.go)) treats Application resources as reconciliation targets. It pulls the declared Git source, renders manifests (including nested CRDs), and applies them to destination clusters using server-side apply or strategic merge patching depending on the resource type.

## CRD Lifecycle Management in Argo CD

Managing CRDs through Argo CD requires understanding the complete lifecycle from installation to deletion.

### Installation and Versioning

Argo CD installs CRDs through Helm charts or plain manifests in `manifests/install*.yaml`. Once installed, the controller monitors CRD health via `status.conditions` such as `Established` and `NamesAccepted`. Health check definitions reside in `resource_customizations/apiextensions.k8s.io/CustomResourceDefinition/`, providing custom health assessment logic for the CRD resource type itself.

### Synchronization Ordering

When syncing Applications containing CRDs, Argo CD performs the following sequence:

1. **Apply CRD manifests** to the target cluster
2. **Wait for `Established` condition** using the health check customization
3. **Apply dependent Custom Resources** once the API is available
4. **Verify resource health** before marking sync successful

This ordering prevents race conditions where operators or controllers attempt to watch resources before their definitions exist.

### Deletion and Cascade Behavior

Deleting an Application that owns CRDs triggers cascade deletion only when `metadata.ownerReferences` links the CRD to the Application. The controller respects Kubernetes `propagationPolicy` settings to avoid orphaned resources. Set `prune: false` in sync policies to preserve CRDs when deleting parent Applications.

## Practical Examples

### Deploying Applications with Embedded CRDs

When packaging operators with Argo CD, include the CRD in your Application source. The controller detects the CRD kind and applies it before operator deployments:

```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: nginx-operator
spec:
  project: default
  source:
    repoURL: https://github.com/example/nginx-operator
    path: helm
    helm:
      valueFiles:
      - values.yaml
  destination:
    server: https://kubernetes.default.svc
    namespace: nginx-operator
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

```

The Helm chart's [`templates/crd.yaml`](https://github.com/argoproj/argo-cd/blob/main/templates/crd.yaml) deploys first, waits for `Established` status, then proceeds with the operator Deployment and Custom Resource instances.

### Generating CRD-based Applications with ApplicationSet

For multi-tenant environments where each tenant requires its own CRD definition, use ApplicationSet generators:

```yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: multi-tenant
spec:
  generators:
    - git:
        repoURL: https://github.com/example/multi-tenant-repo
        directories:
          - path: tenant-*
  template:
    metadata:
      name: '{{path.basename}}'
    spec:
      project: default
      source:
        repoURL: https://github.com/example/multi-tenant-repo
        targetRevision: HEAD
        path: '{{path}}'
      destination:
        server: https://kubernetes.default.svc
        namespace: '{{path.basename}}'

```

Each generated Application may contain tenant-specific CRDs. Argo CD ensures these definitions reconcile before creating tenant Custom Resources.

### Monitoring CRD Health in the UI

The Argo CD UI renders CRD status using custom health checks defined in [`ui/src/app/applications/components/resources.ts`](https://github.com/argoproj/argo-cd/blob/main/ui/src/app/applications/components/resources.ts) (around line 44). The mapping logic interprets `status.conditions` to display "Established," "Progressing," or "Degraded" badges, providing visual feedback on CRD readiness before dependent resources deploy.

## Key Source Files and Implementation Details

Understanding these specific files in the `argoproj/argo-cd` repository clarifies how CRDs integrate with the GitOps engine:

- **[`manifests/crds/application-crd.yaml`](https://github.com/argoproj/argo-cd/blob/main/manifests/crds/application-crd.yaml)** – Core Application API schema with OpenAPI validation
- **[`manifests/crds/appproject-crd.yaml`](https://github.com/argoproj/argo-cd/blob/main/manifests/crds/appproject-crd.yaml)** – AppProject RBAC and scope definitions  
- **[`manifests/crds/applicationset-crd.yaml`](https://github.com/argoproj/argo-cd/blob/main/manifests/crds/applicationset-crd.yaml)** – ApplicationSet generator specifications
- **[`gitops-engine/pkg/sync/sync_context.go`](https://github.com/argoproj/argo-cd/blob/main/gitops-engine/pkg/sync/sync_context.go)** – Dynamic client initialization for CRD watching
- **[`gitops-engine/pkg/sync/sync_tasks.go`](https://github.com/argoproj/argo-cd/blob/main/gitops-engine/pkg/sync/sync_tasks.go)** – Task ordering logic ensuring CRDs apply before dependents
- **`resource_customizations/apiextensions.k8s.io/CustomResourceDefinition/`** – Health check expressions for CRD status
- **[`hack/gen-crd-spec/main.go`](https://github.com/argoproj/argo-cd/blob/main/hack/gen-crd-spec/main.go)** – Code generator extracting CRD definitions from Go structs
- **[`ui/src/app/applications/components/resources.ts`](https://github.com/argoproj/argo-cd/blob/main/ui/src/app/applications/components/resources.ts)** – Frontend resource type mapping and health display

## Summary

- **Argo CD CRDs** (`applications`, `appprojects`, `applicationsets`, `argocdconfigs`, `argocdnotifications`) extend Kubernetes to support GitOps-native workflows
- The **gitops-engine** orders synchronization tasks to apply CRDs before dependent resources, preventing race conditions
- **Health checks** in `resource_customizations/` monitor CRD `status.conditions` to ensure definitions reach `Established` state
- **ApplicationSets** can generate Applications containing CRDs, enabling automated provisioning of operator-backed services
- The **code generator** at [`hack/gen-crd-spec/main.go`](https://github.com/argoproj/argo-cd/blob/main/hack/gen-crd-spec/main.go) ensures CRD schemas remain synchronized with Go struct definitions

## Frequently Asked Questions

### What CRDs does Argo CD install by default?

Argo CD installs four core CRDs: `applications.argoproj.io` for GitOps application definitions, `appprojects.argoproj.io` for project scoping and RBAC, `applicationsets.argoproj.io` for application templating, and `argocdconfigs.argoproj.io` for server configuration. An optional fifth CRD, `argocdnotifications.argoproj.io`, supports notification configuration. These reside in `manifests/crds/` and establish the API group `argoproj.io`.

### How does Argo CD handle CRD dependencies during synchronization?

Argo CD uses task ordering logic in [`gitops-engine/pkg/sync/sync_tasks.go`](https://github.com/argoproj/argo-cd/blob/main/gitops-engine/pkg/sync/sync_tasks.go) to classify CRDs as prerequisite resources. The sync context applies CRD manifests first, waits for the `Established` condition using health checks defined in `resource_customizations/apiextensions.k8s.io/CustomResourceDefinition/`, then proceeds with Custom Resource instances. This ordering prevents "resource not found" errors during automated syncs.

### Can Argo CD manage CRDs for other operators?

Yes. Argo CD can deploy and manage CRDs defined in external repositories or Helm charts. When an Application references a manifest containing a CRD, the controller treats it like any other resource but applies special ordering logic. You can disable automated pruning for CRDs to prevent accidental deletion of operator definitions while allowing Application updates.

### How are Argo CD's own CRDs generated from source code?

The repository includes [`hack/gen-crd-spec/main.go`](https://github.com/argoproj/argo-cd/blob/main/hack/gen-crd-spec/main.go), a code generation utility that extracts OpenAPI v3 schemas from Go struct tags and comments. This ensures the YAML definitions in `manifests/crds/` remain synchronized with the underlying Go types used by the application controller, reducing schema drift between API versions.