How is everyone monitoring workflow executions?

I need to start monitoring workflows better.

How are you guys doing it?

@patriciaLee the native answer most people miss is the Error Workflow, set one globally in Settings and it fires on any failed execution so you can push the error to slack/email/wherever without polling anything. for browsing/auditing theres the Executions view with status filters. and if youre self-hosted, set N8N_METRICS=true to expose a prometheus /metrics endpoint you can scrape into grafana for dashboards and alerting. error workflow + metrics covers most production setups.

There are two categories that I assess. The first category is execution health. I want to know whether the execution started, finished, or encountered an error. The other category is business outcome. I have to determine whether the execution did what it was supposed to do. This category is more difficult to assess. For example, if an execution caused a filter to skip all records, then the execution would be successful while completely useless.

If a workflow is important enough, I will record more specifics including the number of records processed, the final status of the workflow, the reason for the workflow failing, the owner of the workflow, and the proposed next step.

In addition to errors, I monitor some other symptoms. For example, if workflows have not completed successfully, if the number of records processed falls to 0, or if there is an increasing number of retry attempts, I will issue an alert. I always strive to make alerts actionable.

@patriciaLee achamm covered the core (Error Workflow + Executions view + Prometheus/Grafana) — that’s the right foundation. Two things I’d add that catch what those miss:

  1. Make the Error Workflow actually actionable. A bare “a workflow failed” alert isn’t enough. In your global Error Workflow, push a message that includes the workflow name, the execution URL, the node that failed, and the error message — that turns a 20-minute hunt into a one-click jump to the broken run. Also set EXECUTIONS_DATA_SAVE_ON_ERROR=all (and prune successful runs with the data-prune settings) so you keep failed executions to debug without bloating the DB.

  2. Watch for SILENT failures — the real blind spot. Error Workflow + metrics only fire when a workflow runs and throws. They do NOT catch a workflow that silently stops running — a trigger that dies, a webhook that gets unregistered, a cron that quietly stops. That’s the failure that actually hurts, because you find out days later from the client. The fix is a dead-man’s switch: a Schedule trigger that pings a heartbeat service (Healthchecks, Better Stack, or self-hosted Uptime Kuma) every few minutes. If the ping stops arriving, it alerts you — so you catch “it stopped running at all,” not just “it ran and errored.”

If you’re self-hosted, I’d also put a basic uptime monitor on the n8n instance/container itself, so you know whether the whole thing is down vs. just one workflow.

The layered setup I’d run: Error Workflow with rich context for run-time failures → Prometheus/Grafana for aggregate health → a heartbeat/dead-man’s switch for silent stops → an uptime monitor on the instance. Most people set up the first two; the heartbeat is the one almost everyone forgets until it bites them.

Good point from @ShawnWilliams on distinguishing execution integrity vs. business outcomes. An example from the second category that might help: I built a daily workflow that doesn’t monitor for errors, but for content opportunities — it searches forum posts and evaluates via LLM whether they’re relevant to me, then sends a summary via email.

The point is: “monitoring” doesn’t have to mean just errors. You can use the same error-workflow mechanism to also detect positive triggers, whether that’s new leads, content, or open questions you can answer. The technical foundation (achamms setup) stays the same, only the condition that triggers the alert changes from “error occurred” to “interesting event detected”.

@patriciaLee and others covered the core pieces (Error Workflow, Executions view, Prometheus/Grafana, and the distinction between execution health vs. business outcomes). I’d add one more layer that has bitten me in production: silent failures.

Error Workflows and metrics only help when something actually executes and throws an error. They don’t catch a trigger that stops firing, a webhook subscription that quietly expires (Gmail watches are a classic example), or a cron job that never runs. Nothing executes, so nothing gets observed. In my experience, those are often the most painful failures because you discover them from a customer rather than from monitoring.

The approach I’ve settled on is a dead-man’s switch: a scheduled workflow pings a heartbeat service (Healthchecks.io, Better Stack, or self-hosted Uptime Kuma). If the heartbeat stops arriving, that’s the alert. It complements Error Workflows by detecting “it stopped running entirely,” not just “it ran and failed.”

I also like Shawn’s point about business outcomes. For important workflows, I track things like records processed, retry counts, expected minimum volumes, and ownership. A workflow that successfully processes zero records may be technically healthy but operationally useless, so those metrics deserve alerts too.

The layered model that has worked well for me is:

  • Error Workflow → rich context (workflow, node, execution URL, error details)
  • Prometheus/Grafana → aggregate metrics and trends
  • Business metrics → records processed, retries, expected outcomes
  • Heartbeat/dead-man’s switch → silent failures
  • Uptime monitoring → instance/container health

Most people implement the first two layers. The heartbeat and business-outcome layers are the ones that tend to save you from unpleasant surprises later.

Shawn’s split is the one I’d use: execution health vs business outcome.

For client workflows I’d add a tiny run receipt to the alert: expected window, records touched, account/credential used, downstream action attempted, final record/message id, and who owns the next step. The green execution is less useful than proof of what changed.

This thread already has the important split covered well, execution health versus whether the outcome actually happened, plus the heartbeat idea for the run that never fires, so I will just add the one failure that still slips past all of that. Even with a record-count check and a dead-man switch in place, the case that gets people is the run that completes, processes its usual number of rows, throws nothing, and is still wrong, because a credential quietly expired or a source went stale and the API handed back a valid but empty or placeholder response. The count looks normal, the status is green, nothing errors, so none of the layers above flag it.

The reason a standard Error Trigger is blind to this is that there was no error. The token did not fail loudly, it returned a clean 200 with nothing useful inside, and the workflow happily mapped that forward. A record-count alert misses it too, because the count can be normal while the contents are stale or blank.

What catches it without much effort is checking the content, not just the presence. After any auth-sensitive call, assert on a field that only shows up when the call genuinely worked, rather than only checking that the response is non-empty, and add a freshness check, is the newest record actually recent or am I looking at yesterday’s data served back to me. For the credential angle specifically, it helps to treat an unexpected empty result from a normally-busy source as a failure condition instead of a quiet success.

The mindset that ties the whole thread together: a green run with a normal row count still is not proof the data is real, only that something came back. The check worth adding is whether the result is fresh and correct, not just present. What do you all do about the stale-but-green case, or has it not bitten you yet?

This thread has the core layers covered well: error workflow with context, Prometheus/Grafana, heartbeat for silent failures, and the green-but-stale case someone raised. One gap I’d add, especially if you’re not running n8n in isolation:

Everything mentioned so far is n8n-native. Error Workflow, N8N_METRICS, the Executions view. That’s the right call if n8n is your only automation surface. But a lot of teams aren’t pure n8n. They’ve got Make scenarios, a couple Zapier zaps, a cron job, maybe a script or two, all doing real production work. Each one has its own dashboard, so “is everything healthy” means checking three or four different places, and the heartbeat pattern people described here has to get rebuilt separately per tool.

The pattern that’s worked for me: treat “did it run, did it succeed, did it fail” as one simple event you fire from wherever the automation lives. One HTTP call from n8n’s success and error paths, same thing from a Make webhook or a Zapier webhook or a try/except in a script, all landing in one place that doesn’t care which tool sent it. Same heartbeat idea as above, just not locked to one platform.

Disclaimer since I should say it outright: I built a tool for exactly this (FlowPulse) after running into this same “four dashboards, no single view” problem myself. Not trying to drop a pitch in the middle of a good thread, just flagging it’s out there in case the cross-platform piece is useful to anyone. Happy to talk through the DIY version too if that’s more your speed.