Argo CD performance with monorepos

Large monorepos can make Argo CD regenerate manifests for applications that never changed. This page explains how to scope regeneration, what each setting trades off, and what to confirm in your environment.

On this page

Why Argo CD performance with monorepos degrades as the repository grows

Argo CD slows down on a large monorepo when every commit to the repository forces every Application that points at it to regenerate its manifests. The cost is not in the commit itself. It sits in the repo-server, which fetches the repository and runs Helm, Kustomize or plain manifest rendering for each Application that is due for a refresh. When one repository holds dozens or hundreds of unrelated services, a change to a single chart can cause work across all of them, and that work multiplies with each new Application, each new cluster and each new path in the tree. The result is slower sync status, longer queues in the repo-server and, eventually, timeouts or memory pressure on the component doing the rendering.

Teams usually need scoping once they see most refreshes produce identical output. The first control to evaluate is the argocd.argoproj.io/manifest-generate-paths annotation on each Application, which limits the commits that trigger manifest regeneration to the paths that Application actually uses. According to the Argo CD high availability guide, this annotation works without webhooks since v2.11, but shallow clones disable its Git-history comparison, so a clone depth decision made for speed can quietly remove the scoping. Periodic refreshes still happen on a schedule, and ARGOCD_RECONCILIATION_JITTER (default 60) spreads them out so that a large fleet does not refresh in lockstep. Confirm which Argo CD version you run before you rely on these behaviors, and measure repo-server queue depth before and after each change.

Before changing anything, inventory which Applications point at the monorepo, which paths each one renders, and how often each one regenerates. An annotation that is too broad saves little, and one that is too narrow can miss a shared values file or a base overlay that a service depends on, leaving that Application out of date without any error. Review the scoped paths with the same care as the manifests themselves, and agree with platform owners who maintains the mapping as services are added or moved. That ownership question, more than any single setting, decides whether the scoping stays correct over the life of the repository.

Which performance setting fits which monorepo pattern

This table compares four settings and the webhook path for large monorepos, showing what each changes, when it fits and what it costs. Read each row against your repository layout: a setting that cuts work for one pattern can hide changes or lose history for another.

SettingWhat it changesWhen it fitsWhat it breaks or costs
argocd.argoproj.io/manifest-generate-pathsLimits which commits trigger manifest regeneration for an application to changes under the listed pathsApps that live in a subdirectory of a shared repo and rarely depend on files elsewhereMissed refreshes if the app reads shared Helm values or Kustomize bases outside the listed paths; list those paths too
Fully qualified targetRevision (refs/heads/main)Removes ambiguity in reference resolution so Argo CD resolves the branch directlyRepos with branches or tags sharing names, or any monorepo where lookup overhead mattersRequires the revision to be written in full; a rename of the branch needs a manifest update
Shallow cloneReduces the data the repo-server fetches and stores for each repositoryVery large history where only the current tree is needed for renderingDisables the Git-history comparison that manifest-generate-paths relies on, so path filtering can no longer be trusted
Webhooks from the Git hostPushes change notifications so Argo CD refreshes on a commit instead of waiting for pollingLarge monorepos with frequent pushes that need fast sync and less polling loadNeeds a reachable endpoint, a shared secret and per-provider setup; a missed webhook falls back to the periodic refresh
ARGOCD_RECONCILIATION_JITTER (default 60)Spreads periodic refreshes across a window so applications do not all refresh at onceMany applications sharing one repo that would otherwise refresh in burstsAdds delay before a refresh runs; it does not replace webhooks or path filters for urgency

How to scope Argo CD applications in a large monorepo

This sequence limits each Argo CD application to the paths it actually renders from, so unrelated commits stop triggering manifest regeneration. Each step ends with a check you can run before moving on.

  1. Inventory the paths each application renders from

    Your platform team lists every Argo CD Application in the monorepo and records the directories its source path, Helm chart, Kustomize base and overlays, and any values files read at render time. Include shared libraries pulled in through Helm dependencies or Kustomize remote bases, since changes there also change output. Write the result as a table with one row per application. Done when a platform engineer can point to the exact directories that would change the rendered manifests for each application, and every shared directory is listed against each application that depends on it.

  2. Add the manifest-generate-paths annotation

    Add the argocd.argoproj.io/manifest-generate-paths annotation to each Application metadata, listing the directories from the inventory as a semicolon-separated set of paths. Use absolute paths beginning with a slash for paths relative to the repository root, and add the shared directories alongside the application's own path. Keep the list short, because every extra path widens the set of commits that trigger regeneration. Commit the change through the normal Git review flow. Verification: after the change syncs, the Application shows the annotation in its live manifest, and the controller logs no errors about the annotation being unparseable.

  3. Set fully qualified target revisions

    Change each Application's targetRevision from a short branch name such as main to a fully qualified reference such as refs/heads/main, and use refs/tags/ for tagged releases. Fully qualified references reduce reference-resolution overhead on every refresh. Apply the change to a single non-production Application first, then roll it through the rest. Verification: the Application's status still resolves to the expected commit SHA after the next refresh, and the revision shown in the UI matches the branch head in Git.

  4. Decide clone depth and its effect on annotation comparison

    Decide whether the repo-server clones full history or a shallow copy. The manifest-generate-paths comparison uses Git history to find which paths changed, and shallow clones disable that comparison, so the annotation has no effect on a shallow clone. Keep full clones for repositories where path scoping matters, and weigh the larger clone size and fetch time against the regeneration savings. Confirm the decision with your Argo CD version and repository size, because clone behavior and cache settings are tuned in the repo-server configuration. Verification: a test commit that touches only an unrelated path leaves the Application's refresh state unchanged, which confirms the comparison is working.

  5. Configure webhooks for each Git provider

    Register a webhook from the Git host to Argo CD for each repository, using the endpoint your Argo CD API server exposes and a shared secret stored in the argocd-secret. Set the webhook to send push events for the branches and tags Argo CD watches. Each provider has its own payload format and size behavior, so confirm the event types, payload limits and secret header for your host before enabling it. Verification: push a commit to a watched path and confirm Argo CD logs the webhook receipt and refreshes only the affected applications. Push a commit to an unrelated path and confirm no refresh is logged for it.

  6. Confirm reconciliation jitter

    Check the ARGOCD_RECONCILIATION_JITTER setting on the application controller, which spreads periodic refreshes across time so many applications do not refresh at the same moment. The default is 60. Raise it only after you review how many applications share a cluster and how long refreshes take. Set the value through the controller's environment configuration, then restart the controller. Verification: over one polling interval, the controller's refresh timestamps for applications on the same cluster are spread out rather than clustered, and the refresh queue does not grow.

  7. Test with an unrelated commit and record the result

    Make a commit that touches a directory outside every application's annotation list, then check each Application's status for a pending refresh or a new manifest generation. Repeat with a commit inside one application's path and confirm only that application refreshes. Store the results in your change record with the commit SHAs and timestamps. Verification: an unrelated commit marks no application for refresh, and an in-scope commit marks exactly the expected applications. If the results differ, return to the inventory and correct the path list before expanding the change to more applications.

Where manifest-generate-paths goes wrong

The main failure mode of the argocd.argoproj.io/manifest-generate-paths annotation is that it narrows regeneration. Argo CD only regenerates manifests for an application when a commit touches one of the listed paths, so any file the manifests depend on but the list omits can change without the application ever refreshing. A shared Helm values file in a common/ directory, a Kustomize base referenced by an overlay, or a chart in a sibling folder are typical examples. The application then reports as in sync while the rendered output it should reflect is stale, which is harder to notice than a failed sync because nothing visibly errors.

Review each annotated application against its full dependency graph before relying on it. For Helm, list every values file passed through valueFiles, every local chart dependency and any file pulled in through $values references. For Kustomize, follow every resources, bases, components and patch reference to the file that contains it. Check how the annotation is written too: it accepts relative paths that Argo CD resolves against the repository, so a path that works for one application can silently match nothing for another. Treat any file outside the listed paths that the application reads as a reason to widen the list or to split the application.

Do not assume webhooks cover the gap. The Argo CD high availability guide says the annotation works without webhooks since v2.11, but a webhook only tells Argo CD that something changed, and the path filter still decides what gets regenerated. Test with real commit histories: replay recent merges that touched shared files, confirm each affected application refreshes, and check that unrelated commits leave it alone. Repeat this after each new shared file or chart is introduced. Record the results as part of the change process, so the list of paths is reviewed like code rather than set once and forgotten.

Security and operational considerations for scoped refreshes

Scoped refreshes cut repository work, but they add an inbound webhook, a repo-server that runs tools on repository content, and path annotations that live in Git and can be changed by any reviewer. Each card below names one of these points and what to check before and after a change.

Webhook shared secrets

A webhook that triggers refreshes is an inbound endpoint on your Argo CD installation. Configure a shared secret for each Git provider so Argo CD can verify that a push notification came from the Git host and not from a stranger. Rotate the secret through your normal secret process, and confirm that the value is stored in a Kubernetes Secret rather than in a manifest committed to Git.

Webhook endpoint exposure

Decide which network paths can reach the webhook endpoint and keep everything else closed. Only the Git provider's published source ranges, or a controlled ingress path, should reach it. Review the ingress rules alongside the API server exposure so that the webhook route does not quietly widen the attack surface of the whole installation. Test the route after every ingress change.

Repo-server runs repository content

The repo-server executes Helm and Kustomize against files from Git. Anyone who can push a repository that Argo CD reads can influence what those tools do on the repo-server. Treat untrusted repositories as a risk, restrict which repositories each project may use, and watch for Kustomize or Helm inputs that reach files outside the intended directory, since out-of-tree file access is a documented concern.

Path annotations in code review

The argocd.argoproj.io/manifest-generate-paths annotation decides which commits can trigger regeneration. A path set too narrowly can hide a change that should deploy, and one set too broadly brings back the full repository cost. Require reviewers to check annotation changes in the same way they check manifest changes, and confirm that every shared Helm chart or Kustomize base path is covered by the applications that consume it.

Monitoring refresh behavior after changes

After a change to annotations, target revisions or webhook settings, watch whether applications refresh when they should and stay quiet when they should not. Compare the expected set of applications with what actually syncs, and look for applications that stop reacting to commits. Record the baseline before the change so that a regression is visible, and treat an unexpected jump in repo-server activity as a signal to review recent changes.

Limits to confirm in your environment

Does the manifest-generate-paths annotation work on my Argo CD version without webhooks?

Support for the argocd.argoproj.io/manifest-generate-paths annotation without webhooks arrived in v2.11, so any older release needs a different approach. Confirm the exact version you run in production, not the one in your test cluster, and check it against the Argo CD high availability guide. Your platform team owns this check because it depends on the installed image tag. Ask them to record the version in the change ticket, then confirm during a test sync that a commit outside the declared path leaves the Application's status untouched. If the version is older than v2.11, plan an upgrade first, because the upgrade path itself has breaking changes to review.

How does my Git host send push events to Argo CD?

Path-scoped refresh depends on how and whether your Git host delivers push events, so inventory each provider before you change any annotation. Confirm with your source control administrators which hosts send webhooks, which events they include, whether payloads reach Argo CD's endpoint from the network where it runs, and who holds the shared secret. Also check whether a proxy or web application firewall truncates large push payloads, since a monorepo push can carry many changed files. Without a delivery path, Argo CD falls back to periodic polling, so the annotation still limits regeneration but refresh timing is less predictable. Write down the answer for each repository.

Do shallow clones break path-based manifest generation?

Shallow clones disable the Git-history comparison that path-based refresh relies on, so a shallow repository may regenerate more often than you expect. Ask your repository owners whether any Application uses a shallow clone configuration, and whether the repo-server or a plugin enables one. Then test one application with a commit that touches only its own path and one that touches a neighboring path, and compare what Argo CD regenerates. Anyone who changes clone depth for speed should understand that the trade-off lands on refresh behavior, so review it with the team that owns the repository and the Argo CD administrators together.

Can my repository layout support clean path boundaries?

Path boundaries work only when each application's inputs sit in directories that other applications do not read. Check whether shared Helm charts, common Kustomize bases, or values files outside an application's folder feed several Applications. If they do, a commit to the shared directory correctly triggers regeneration for every consumer, but the annotation cannot narrow it further. Ask the platform architects to map each Application's source path and every external reference it resolves, then decide whether shared content should move into its own declared path or stay where it is. This mapping usually takes longer than the annotation change itself, so budget review time with the application owners.

Who should confirm these limits before a rollout?

Three groups should sign off: Argo CD administrators, source control administrators and the application teams that own each path. Argo CD administrators confirm the version, controller and repo-server configuration, and whether webhooks reach the endpoint. Source control administrators confirm delivery of push events, payload limits and secret handling. Application teams confirm which directories their Applications really read, including shared charts and values. Record each answer in the runbook for the repository. If one group cannot answer, treat that repository as not ready for path-scoped refresh and keep its current behavior until the answer arrives.

What does a path-scoping rollout cost and who pays for it?

The annotation itself is a small configuration change, so most of the cost comes from discovery, testing and review. Internal teams pay for their time to map paths, run test commits and update runbooks, and an upgrade to a supported version adds its own effort. A partner, if you hire one, bills for the scoped work in a fixed-scope quote, which is agreed in writing before work starts. Ask for the quote to list the repositories in scope, the version checks, the webhook verification steps and the test plan. Costs recur only when repositories are added or layouts change, so ask whether a retainer would cover that ongoing review. DeployOpen does not publish a price list, so the written scope determines the figure.

How do I verify that path scoping actually reduces regeneration?

Verify with controlled commits, then check what Argo CD actually regenerated, rather than assuming the annotation works. Create a test branch, change one file inside an Application's path and another file outside it, and watch the Application's refresh and manifest generation events. Repeat the test once with webhooks enabled and once with polling only, because the delivery path changes timing. Keep the test results with the change record so auditors and operators can see the evidence. If the outside commit still triggers regeneration, check the shallow clone setting, the annotation spelling and the version first.

When scoping stops being enough

Path scoping reduces how often Argo CD regenerates manifests, but it does not shrink the repository, reduce the number of Applications, or lower the load on the application controller. A manifest-generate-paths annotation keeps an unrelated commit from triggering a render, yet every Application still exists, every cluster is still reconciled on its interval, and the repo-server still has to clone and index the same tree. Teams that expect scoping to fix a slow UI or a backlog of OutOfSync states often find the bottleneck was never the render step. Before you conclude that scoping has worked, check the controller and repo-server logs and the Application count per cluster, not only the number of renders you avoided.

Several signals suggest the next step is a different change. If the application controller is saturated on one cluster while others are idle, look at controller sharding so that cluster can be pinned to its own replica. If manifest generation is slow or repo-server pods are being killed for memory, the problem is in the render path, so tune the repo-server before adding more Applications. If many teams need commits to move independently with separate access, release cadences or audit boundaries, the repository layout itself may need to change. Each of these has its own decision points, and the sibling topics on controller sharding, repo-server tuning, large application counts and webhooks cover them in detail.

Confirm these points with your own environment before you decide: how many Applications each controller shard manages, how long a typical refresh takes under load, and whether commits to unrelated paths still produce visible repo-server activity after the annotations are in place. Record a baseline first so that any later change can be measured against it. If the baseline shows that scoping has already done its job, the remaining cost is usually in controller capacity or repository structure, and that is where a planning conversation with a partner should start.

Questions teams ask before scoping a monorepo for Argo CD

What drives the cost of a monorepo performance project for Argo CD?

The cost follows the amount of analysis and change needed, mostly the number of Applications and ApplicationSets that point into the repository, how many distinct paths and tools (Helm, Kustomize, plain YAML) they use, and how many clusters and environments must be tested. Each Application needs its generate paths reviewed, so a repository with hundreds of Applications carries more work than one with a few dozen. Git host configuration adds effort when webhooks must be created, secured and verified per provider. Testing is often the largest variable, because a wrong path filter can silently skip a needed sync. Ask any provider for a written scope that lists these counts, the Git hosts involved, and what evidence of testing you will receive. DeployOpen fixes scope and deliverables in writing before work starts, and the quote follows from that scope.

How long does a monorepo performance engagement take?

Duration depends on the same drivers as cost: the number of Applications, the complexity of their path layouts, the Git hosts and webhook work involved, and the testing required before a change reaches production. A narrow scope covering one repository and a handful of Applications is far shorter than a rewrite of how an entire organization models its monorepo. Because most engagements are fixed-scope, the timeline is agreed in writing alongside the deliverables rather than estimated in the abstract. Ask for milestones that separate analysis, a staging rollout and production cutover, since a staging rollout is where slow or missed refreshes are caught. Your scoping conversation should also confirm change freeze windows, because those set the earliest practical production date.

What does our team need to provide during a monorepo project?

The work needs decisions and access from your side more than it needs time from every developer. You will need an owner who knows the repository layout and which directories each team's applications read, read access to the Argo CD configuration and Application manifests, and administrative access to the Git host so webhook endpoints and shared secrets can be configured. Someone must also confirm which branches and tags each Application tracks, because the fully qualified target revision change depends on it. Finally, your platform team needs to approve the change window and the rollback approach. Put these responsibilities into the written scope so that a missing approval does not become a hidden delay.

Can our internal platform team handle monorepo tuning without a partner?

Yes, many teams can, provided they have engineers who understand Argo CD's reconciliation model and can test changes safely. The core techniques are documented in the Argo CD high availability guide, including the manifest-generate-paths annotation, fully qualified refs such as refs/heads/main in targetRevision, and the ARGOCD_RECONCILIATION_JITTER setting. The risks sit in the details: a path filter that is too narrow can stop a required sync, shallow clones remove the Git-history comparison that the annotation relies on, and webhook misconfiguration can leave applications refreshing late. If your team has the capacity to write tests for each Application's paths and to monitor refresh behavior after the change, doing it internally is practical. If not, a fixed-scope engagement can cover the analysis and testing while your team keeps ownership of the result.

Which parts of a monorepo change are most likely to cause problems?

The most common failures come from path filters that exclude files an Application actually renders. An Helm chart that reads a values file from a shared directory, or a Kustomize overlay that references a base outside its folder, can stop updating if the annotation does not list those paths. Shallow clones are another trap, because they disable the Git-history comparison the annotation uses, so teams should confirm how their repo-server fetches repositories before relying on it. Webhook gaps are also common, particularly when branch or tag naming does not match what the Application tracks. Before cutover, verify that a commit touching each shared path triggers the expected refresh, and keep a documented way to force a hard refresh if something is missed.

Do monorepo changes affect our security posture?

They can, mainly because the repo-server runs Helm and Kustomize on repository content, so the paths an Application reads are part of your trust boundary. Path filters should narrow when regeneration happens, not widen what the repo-server can read. Webhook endpoints should use shared secrets, and the Argo CD security documentation covers TLS between components and redaction of credentials in logs and API responses. Changes to repository credentials should follow the same review process as other access changes. Ask the scope to include a review of who can change Application path annotations, since a single edit to an annotation can alter what gets deployed.

What should we ask for in a written scope before signing?

A useful scope lists the Argo CD version and installation you are running, the number of Applications and ApplicationSets in scope, each repository and its Git host, and the tools each Application uses. It should name the changes to be made, such as annotations, target revision format and webhook configuration, and the test evidence you will receive for each one. Ask who performs staging and production cutover, what rollback looks like, and what the client team must provide and approve. Confirm whether follow-up support or a retainer is included after go-live, because refresh behavior often needs review once real commit traffic arrives. Finally, check that the scope states what is excluded, so the quote reflects the work you actually need.

How DeployOpen scopes and delivers monorepo tuning

DeployOpen plans, implements, tests and documents Argo CD performance changes inside your own infrastructure. We start from how your monorepo is laid out and which commits currently trigger regeneration, then agree the changes in writing before any work begins.

How we scope

  • Map the monorepo layout, application paths and the commits that currently trigger manifest regeneration.
  • Record each target revision and whether it is a fully qualified reference or a short branch name.
  • Agree in writing whether the engagement covers annotations, refresh jitter, webhooks or clone strategy.
  • Engagements are fixed-scope, with deliverables and timelines confirmed before work starts.

How we build

  • Add manifest-generate-paths annotations to applications and check them against sample commits.
  • Update targetRevision values to fully qualified refs and confirm each application still syncs.
  • Set reconciliation jitter and webhook configuration to match the agreed refresh behavior.
  • Test shallow clone settings against the Git-history comparison before anything reaches production.

How we hand over

  • Deliver a written record of each application, its generate paths, revision format and refresh settings.
  • Document how to verify that an unrelated commit no longer regenerates a given application.
  • Walk your platform team through the configuration and the trade-offs behind each change.
  • Provide operating notes for adding new applications to the monorepo without undoing the tuning.

How we support

  • Ongoing support, upgrades and continuous testing are available as retainers.
  • Retainers can cover reviews of new applications and checks after each Argo CD minor release.
  • Ask any provider to confirm which Argo CD versions their support covers before signing.
  • Quotes follow from the written scope, so request the scope and deliverables in writing first.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.