Why deployment events need a voice
In a GitOps setup nobody runs a deployment command and watches it finish. A merge happens, a controller picks it up minutes later, and the result sits inside a dashboard that few people open. When a sync fails because a CRD is missing or a chart version does not exist, the author of the change has often moved on to something else. The failure is found by a customer, or by whoever opens the ArgoCD UI next.
Notifications close that gap. They put the outcome of every meaningful deployment event in front of the people responsible, with enough context to act. This page covers how we design them inside our GitOps, Helm, ArgoCD and Flux service, and what we deliberately leave out.
What good looks like
- A failed sync reaches the owning team’s channel within a minute or two, with the error text.
- A message links to the commit, the author, the application and the diff.
- Staging noise stays in staging channels; production events are visible and calm.
- Nobody mutes the channel, because nearly every message needs a decision.
- Notification setup lives in git like everything else, so it is reviewed and reproducible.
What to notify on
| Event | Notify? | Where |
|---|---|---|
| Sync failed | Always | Owning team channel |
| Health degraded after sync | Always | Owning team channel, production also to on-call |
| Out of sync in production for longer than expected | Yes | Platform channel |
| Rollout paused or aborted | Yes | Owning team channel |
| Sync succeeded in production | Optional | Quiet deployment log |
| Sync succeeded in staging or dev | Usually no | Nowhere, or a log channel |
The failure of most notification setups is volume. A rule of thumb we apply: if a message does not lead to a person doing something, it should not interrupt anyone.
How it works in practice
ArgoCD Notifications
The notifications controller ships with ArgoCD. You configure a service, a template and a trigger in the argocd-notifications-cm config map, and applications subscribe through annotations. A shortened example:
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
service.slack: |
token: $slack-token
template.sync-failed: |
message: |
:red_circle: *{{.app.metadata.name}}* failed to sync.
Revision: {{.app.status.sync.revision}}
Error: {{.app.status.operationState.message}}
{{.context.argocdUrl}}/applications/{{.app.metadata.name}}
trigger.on-sync-failed: |
- when: app.status.operationState.phase in ['Error', 'Failed']
send: [sync-failed]
An application then opts in with the annotation notifications.argoproj.io/subscribe.on-sync-failed.slack: payments-alerts. The Slack token lives in the notifications secret, which we manage with Sealed Secrets or External Secrets and never in plain git.
Flux notifications
Flux splits the job into a Provider and an Alert. The Provider defines the destination, and the Alert selects which controllers’ events go there:
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Provider
metadata:
name: slack-payments
namespace: flux-system
spec:
type: slack
channel: payments-alerts
secretRef:
name: slack-webhook
---
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
name: payments-failures
namespace: flux-system
spec:
providerRef:
name: slack-payments
eventSeverity: error
eventSources:
- kind: Kustomization
name: payments
- kind: HelmRelease
name: payments-api
API versions for these resources have changed across Flux releases, so we pin and check them against the version you run. Flux can also report status back to your git host as commit status, which shows deployment success beside the pull request.
Microsoft Teams
Both tools can reach Teams through its supported webhook or workflow integration. Because Microsoft has changed how incoming webhooks work, we check the current mechanism for your tenant at setup time rather than assuming an old guide still applies.
Routing, ownership and escalation
One channel for everything fails at the first busy week. We route by application owner, using a label or annotation on each application and a naming convention for channels, so adding a service does not mean editing a central file. Production failures can go to the team channel and also to the on-call tool through Alertmanager or your pager, aligned with incident response practice. Staging stays in a separate channel with a lower expectation.
For clusters managed through ApplicationSets, subscriptions can be set in the template so that every generated application inherits the same rules.
Decisions and trade-offs
Chat only or chat plus git status. Commit status is quieter and sits where reviewers already look. Chat is faster to catch attention. Many teams want both.
Notifier in the GitOps tool or a custom bot. Built-in notifiers cover most needs with less to run. A custom bot only makes sense for special workflows such as approvals.
Rich templates or short ones. Long messages get skipped. We keep four or five fields and link out for detail.
A worked example: a failed release at five in the afternoon
A developer merges a change that references a ConfigMap key that does not exist. The sync starts, the new pods fail to start, and the application becomes degraded. Within a minute the team channel receives a message naming the application, environment, author and revision, with the pod error text and a link to the diff. The author sees it before leaving, reverts the commit, and the controller restores the previous state.
Without that message the first signal would be a customer report the next morning. The configuration above takes under a day to build, and it removes the most common delay in GitOps incidents: nobody knowing that a deployment failed.
Common failure modes
- Alert fatigue from success messages in every environment.
- A silent notifier because a token expired or a webhook was revoked. We add a heartbeat check or an alert on the notification controller itself.
- Missing context, such as “sync failed” with no error text.
- No owner for events from shared applications, so no one reacts.
- Secrets in the config pasted into git.
Delivery and handover
You receive the notifier configuration in git, message templates, channel routing conventions and a short guide for subscribing a new application. We run a deliberate failure in staging with your team watching, so everyone sees what a real alert looks like and who is expected to respond. This connects naturally to wider monitoring.
How to tell it is working
Failed deployments are discovered by the team that caused them, not by users. The channel stays readable. Mean time from failed sync to acknowledgement is short and falling. To design this for your teams, book a consultation.