# Argo CD Resource Hooks: Synchronization Phases and Lifecycle Management

> Learn about Argo CD resource hooks, custom Kubernetes resources attached to application sync lifecycle points using the argocd.argoproj.io/hook annotation for better management.

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

---

**Argo CD resource hooks let you attach custom Kubernetes resources—typically Jobs, Pods, or Argo Workflows—to specific points in the application sync lifecycle using the `argocd.argoproj.io/hook` annotation.**

In the `argoproj/argo-cd` project, resource hooks enable complex deployment patterns like database migrations, smoke tests, and cleanup operations by executing arbitrary resources at predetermined phases of the synchronization process. These hooks integrate with Argo CD's **sync waves** and **deletion policies** to provide fine-grained control over application lifecycle events.

## What Are Argo CD Resource Hooks?

Argo CD resource hooks are Kubernetes resources annotated with `argocd.argoproj.io/hook` that execute during specific phases of the application synchronization lifecycle. Unlike standard application resources, hooks run independently and can succeed or fail without necessarily blocking the main deployment—though failure behavior depends on the specific phase.

The annotation accepts six possible values:

- **PreSync** – Runs before the main synchronization begins
- **Sync** – Runs during the main synchronization phase
- **PostSync** – Runs after successful completion of the sync
- **SyncFail** – Runs only when the sync itself fails
- **PreDelete** – Runs before application resources are deleted
- **PostDelete** – Runs after application resources are deleted
- **Skip** – Excludes the resource from hook execution entirely

According to the implementation in [`gitops-engine/pkg/sync/hook/hook.go`](https://github.com/argoproj/argo-cd/blob/main/gitops-engine/pkg/sync/hook/hook.go), Argo CD parses these annotations to determine resource placement within the synchronization orchestration.

## Sync Phases and Execution Order

Argo CD determines hook execution order through a hierarchical sorting mechanism implemented in [`gitops-engine/pkg/sync/sync_phase.go`](https://github.com/argoproj/argo-cd/blob/main/gitops-engine/pkg/sync/sync_phase.go). The system groups resources first by phase, then applies secondary sorting criteria.

### Phase Ordering

Resources execute in strict phase order:

1. **PreSync** – Pre-deployment tasks like schema migrations
2. **Sync** – Main application resources and inline hooks
3. **PostSync** – Post-deployment verification and notifications
4. **SyncFail** – Failure recovery and alerting (only executes if sync fails)

Hooks never run during selective sync operations. If any hook fails during PreSync, Sync, or PostSync phases, the entire synchronization stops immediately.

### Wave and Kind Ordering

Within each phase, Argo CD applies the following sorting logic:

1. **Sync Wave** – Resources are ordered by the `argocd.argoproj.io/sync-wave` annotation value from lowest to highest (negative waves execute first)
2. **Kind** – Namespaces deploy before other resources, followed by custom resource definitions
3. **Name** – Alphabetical order serves as the final tie-breaker

This ordering ensures that dependencies resolve correctly before dependent hooks execute.

## Hook Deletion Policies

Resource hooks persist in the cluster unless explicitly removed via the `argocd.argoproj.io/hook-delete-policy` annotation. The available deletion policies include:

- **HookSucceeded** – Deletes the hook resource after successful completion
- **HookFailed** – Deletes the hook resource if it fails
- **BeforeHookCreation** – Deletes the previous hook resource before creating a new one (default behavior)

The deletion policy implementation ensures that failed hooks remain available for debugging unless explicitly configured otherwise.

## Deletion Hooks (PreDelete and PostDelete)

Argo CD provides specialized hook phases for application deletion workflows:

- **PreDelete** hooks execute before any application resources are removed and block deletion until they succeed. This enables graceful shutdown sequences, backup operations, or external dependency notifications.

- **PostDelete** hooks run after all application resources are deleted. Unlike other phases, a failing PostDelete hook does not recreate the Application; instead, it leaves a `DeletionError` condition on the Application resource for manual cleanup.

These hooks are validated in [`test/e2e/hook_test.go`](https://github.com/argoproj/argo-cd/blob/main/test/e2e/hook_test.go), which contains comprehensive end-to-end tests for all hook phases including deletion behaviors.

## Practical Examples

### PostSync Notification Hook

Run a Slack notification after successful deployment:

```yaml
apiVersion: batch/v1
kind: Job
metadata:
  generateName: app-slack-notification-
  annotations:
    argocd.argoproj.io/hook: PostSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
        - name: slack-notification
          image: curlimages/curl
          command:
            - curl
            - -X
            - POST
            - --data-urlencode
            - >-
              payload={"channel":"#ops","text":"Argo CD sync succeeded","icon_emoji":":rocket:"}
            - https://hooks.slack.com/services/...
      restartPolicy: Never
  backoffLimit: 2

```

### PreSync Database Migration

Execute database migrations before the main sync using wave -1:

```yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: db-migrate
  annotations:
    argocd.argoproj.io/hook: PreSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
    argocd.argoproj.io/sync-wave: "-1"
spec:
  ttlSecondsAfterFinished: 360
  template:
    spec:
      containers:
        - name: psql
          image: my-postgres-data:11.5
          env:
            - name: PGPASSWORD
              value: admin
          command: ["psql", "-h", "my_postgresql_db", "-U", "postgres", "-f", "preload.sql"]
      restartPolicy: Never
  backoffLimit: 1

```

### Skipping Helm-Generated Hooks

Exclude Helm-generated hooks that would otherwise block synchronization:

```yaml
ingress-nginx:
  controller:
    admissionWebhooks:
      annotations:
        argocd.argoproj.io/hook: Skip

```

## Implementation in the Argo CD Codebase

The core logic for Argo CD resource hooks resides in several key locations:

- **[`gitops-engine/pkg/sync/hook/hook.go`](https://github.com/argoproj/argo-cd/blob/main/gitops-engine/pkg/sync/hook/hook.go)** – Defines hook type parsing and phase categorization logic
- **[`gitops-engine/pkg/sync/sync_phase.go`](https://github.com/argoproj/argo-cd/blob/main/gitops-engine/pkg/sync/sync_phase.go)** – Implements the phase mapping and execution ordering algorithms
- **[`test/e2e/hook_test.go`](https://github.com/argoproj/argo-cd/blob/main/test/e2e/hook_test.go)** – Contains end-to-end tests validating PreSync, Sync, PostSync, SyncFail, PreDelete, and PostDelete behaviors
- **[`docs/user-guide/sync-waves.md`](https://github.com/argoproj/argo-cd/blob/main/docs/user-guide/sync-waves.md)** – User-facing documentation for hook phases and wave configuration

These files work together to parse annotations, sort resources into execution phases, and manage the lifecycle of hook resources during synchronization operations.

## Summary

- Argo CD resource hooks use the `argocd.argoproj.io/hook` annotation to execute Jobs, Pods, or Workflows at specific synchronization phases.
- Execution follows strict ordering: **PreSync** → **Sync** → **PostSync** → **SyncFail**, with **PreDelete** and **PostDelete** handling application removal.
- Within phases, resources sort by **sync-wave** (lowest to highest), then **Kind**, then **Name**.
- The `argocd.argoproj.io/hook-delete-policy` annotation controls cleanup behavior with options for `HookSucceeded`, `HookFailed`, and `BeforeHookCreation`.
- PreDelete hooks block application deletion until completion, while PostDelete hooks run asynchronously after resource removal.

## Frequently Asked Questions

### What happens if a PreSync hook fails?

If a PreSync hook fails, Argo CD stops the entire synchronization process before applying any main application resources. The sync status reports as failed, and the application remains at its previous version until the hook succeeds or is removed.

### Can I use resource hooks with selective sync?

No, hooks do not execute during selective sync operations. According to the implementation in [`gitops-engine/pkg/sync/sync_phase.go`](https://github.com/argoproj/argo-cd/blob/main/gitops-engine/pkg/sync/sync_phase.go), selective sync bypasses the standard phase orchestration to apply only specific resources, excluding hook processing.

### How do sync waves interact with hooks?

The `argocd.argoproj.io/sync-wave` annotation works within hook phases to establish execution order. Resources with lower wave numbers (including negative values) execute before higher numbers. This allows you to chain multiple hooks sequentially, such as running a schema migration at wave -1 and a data validation at wave 0 during the PreSync phase.

### What is the difference between Skip and HookSucceeded deletion policies?

**Skip** is a hook type that prevents Argo CD from treating a resource as a hook entirely, causing it to sync normally with the application. **HookSucceeded** is a deletion policy that removes the resource only after it completes successfully. Skip changes whether Argo CD recognizes the resource as a hook, while HookSucceeded determines when to clean up recognized hooks.