Learn GitOps with ArgoCD - Sync Windows & Scheduling
Episode 14 of 36

Learn GitOps with ArgoCD - Sync Windows & Scheduling

Control when ArgoCD may sync with Sync Windows: cron-based allow and deny schedules, maintenance windows, change freezes, and manual overrides for emergency deployments.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 13 we mastered Resource Hooks to control what happens during a sync. But there's a more basic question: when is a sync itself allowed to happen? Late at night when all users are active? A release freeze a week before an audit? High-risk maintenance hours? ArgoCD provides an answer called Sync Windows — scheduled time windows that allow or forbid sync operations, both automatic and manual.

Why does this matter? GitOps spoils us with auto-sync, but not every change is safe at every time. Sync Windows is a governance mechanism that moves the "what time to deploy" decision from human memory into deterministic configuration — part of the change management culture we'll dig into in episode 15.

Basic Concepts

A Sync Window is a rule on the AppProject with three main components:

  • kindallow (permit sync) or deny (forbid sync).
  • schedule — when the window is active, in 5-field cron format (minute, hour, day, month, weekday).
  • duration — how long the window lasts after the schedule is reached.

A window can be scoped to specific applications, namespaces, and clusters, with wildcard support.

Evaluation Rules

  • If no window matches an application → all syncs are allowed.
  • If a matching allow window exists → sync is only allowed while that allow window is active.
  • If a matching deny window is active → sync is rejected, even if an allow window is also active. deny always wins.

Configuring via AppProject

project-prod.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: billing-prod
spec:
  syncWindows:
    - kind: allow
      schedule: "0 9 * * *"
      duration: 2h
      applications:
        - "*-prod"
      namespaces:
        - billing-prod
      clusters:
        - in-cluster
      manualSync: true
    - kind: deny
      schedule: "0 22 * * *"
      duration: 2h
      timeZone: Asia/Jakarta
      applications:
        - "*-prod"

The example above: *-prod applications may auto-sync every day from 09:00–11:00 (and manually anytime, thanks to manualSync: true), but are forbidden from syncing from 22:00–24:00 — a period usually used for maintenance or to minimize late-night release risk.

Note

Windows are project-level: every Application in the project follows the rules. Filtering by applications, namespaces, and clusters is a way to limit scope — not to create per-application windows. There is no native sync window at the Application level.

Managing Windows via the CLI

All window operations are available in the CLI:

Adding and viewing a sync window
argocd proj windows add billing-prod \
  --kind deny --schedule "0 22 * * *" --duration 2h \
  --applications "*-prod"
argocd proj windows list billing-prod
argocd proj windows delete billing-prod <ID>

The argocd proj windows list output shows the ID, STATUS, KIND, SCHEDULE, DURATION, and even MANUALSYNC and SYNCOVERRUN columns — useful for verifying schedules before a big release.

Use Cases

Maintenance Windows

A deny schedule during maintenance hours (e.g. 0 2 * * Sun, 3-hour duration) prevents auto-sync from interfering with database maintenance work. Combined with syncOverrun: true, an already-running sync won't be forcibly cut off mid-way.

Business Hours Restriction

An allow pattern only during office hours, e.g. 0 9 * * 1-5 with an 8-hour duration — outside that, applications can't change without explicit approval.

Change Freeze

Before a big launch or audit, set a deny for a full week:

Change freeze
    - kind: deny
      schedule: "0 0 * * *"
      duration: 24h
      applications:
        - "*-prod"
      clusters:
        - eks-prod

Scheduled Deployments

An allow + syncOverrun combination enables a scheduled deployment window — the production team only receives changes within an agreed window, making coordination with on-call easier.

Timezone & Multiple Windows

  • Timezone — the timeZone field (e.g. Asia/Jakarta) sets the base for interpreting the schedule. Without this field, the schedule follows the ArgoCD server's timezone (recommended to be set to UTC).
  • Multiple windows — one project can have many allow and deny windows; all are evaluated together with the rules above.
  • AND operator — if a window has more than one filter (applications and namespaces), they default to OR. Enable useAndOperator: true when all conditions must be satisfied together.

Manual Override & Emergency Deployment

When a deny window is active, sync is blocked — including manual. For emergency scenarios, ArgoCD provides an explicit override:

Allowing manual sync on a window
argocd proj windows list billing-prod
argocd proj windows enable-manual-sync billing-prod <ID>
argocd proj windows disable-manual-sync billing-prod <ID>

manualSync: true on a window (or enable-manual-sync via the CLI) keeps manual sync allowed even while the deny window is active — ideal for emergency hotfixes, while auto-sync stays locked.

Warning

A manual override is a risky decision usually made for emergency reasons. Restrict who has sync and update permission on the project, and document in a runbook when overrides are allowed — don't let "emergency" become the daily default flow.

Common Pitfalls

  1. Forgetting that deny overrides allow. An allow window does not override an active deny; this wrong expectation often leaves teams puzzled why sync is still blocked.
  2. Misinterpreting the cron schedule. ArgoCD's cron format is 5 fields: 0 22 * * * = 22:00 every day. Test with argocd proj windows list to see the STATUS.
  3. Timezone not set. Server in UTC but the team in Jakarta → a "22:00" window means 05:00 AM local time. Always set timeZone.
  4. manualSync active on every window. If the goal is to prevent production changes, don't set manualSync: true — emergency overrides must be explicit and temporary.
  5. Sync overrun not enabled. Without syncOverrun, a long sync can be forcibly cut when the window ends, leaving a strange state.

Closing

This episode gave you full control over when changes may happen: the allow/deny concept, cron schedules and durations, per-application/namespace/cluster filtering, use cases for maintenance windows, business hours, change freezes, and scheduled deployments, timezone and multiple window handling, and manual overrides for emergency deployments.

The points you should take with you:

  • Sync Windows live on the AppProject and apply to every Application in the project.
  • deny always overrides allow when both are active.
  • manualSync: true is an emergency override mechanism — use it wisely.
  • timeZone matters so schedules match the team's working timezone.
  • syncOverrun prevents a running sync from being cut short by a window change.

Managing when to deploy is only half of governance; the other half is how changes flow through Git. In the next episode 15 we discuss GitOps Workflow & Branch Strategies: trunk-based vs GitFlow, environment directory structures, branch/tag promotion strategies, and PR-based change management. See you in episode 15!

Learn GitOps with ArgoCD - Sync Windows & Scheduling | Learn GitOps with ArgoCD