Skip to content
Marketing Factory Digital GmbH
Contact
Logo Marketing Factory Digital GmbH
  • Agency
    • About us
    • History
  • Services
    • Consulting, Analysis and Strategy
    • Programming and Development
      • Interface Development
      • PIM/ERP Links
      • Custom Development
      • Seamless CMS Integration
    • Agency Retainer
    • Hosting and Support
      • Cloud Strategies
      • Hosting Partners of Marketing Factory
    • Services with Third Parties
  • Technology
    • TYPO3 Agency Marketing Factory
      • TYPO3 Upgrade vs. TYPO3 Relaunch
      • Current TYPO3 Versions: v12 ELTS, v13, v13
      • The TYPO3 Lifecycle
      • Upgrading from TYPO3 v12 to v14
      • Our TYPO3 Extensions
    • Shopware
    • IT Security
      • DDoS Protection
      • Continuous Upgrading
      • Privacy First
    • Tech Stack
      • Commitment to Open Source
      • Technology Selection
      • PHP Ecosystem
      • Containerisation & Clustering
      • Content Delivery Networks
      • Search Technologies
  • References
    • Projects
    • Clients
      • Client List
    • Screenshot of the homepage of the new Maxion Wheels websiteNEW: Relaunch of the corporate website of Maxion Wheels
  • Community
    • Community Initiatives
  • Blog
  • Contact
  • Deutsch
  • English

You are here:

  1. Blog
  2. How We Monitor n8n and Qdrant
Beleuchtetes Armaturenbrett eines Autos bei Nacht. In der Mitte zeigt ein digitales Display 0 mph und eine Spurhaltegrafik. Links ist ein Drehzahlmesser und rechts Analoganzeigen für Kraftstoff und Motortemperatur zu sehen.
  • Tech Stack
  • Hosting
  • n8n
03.08.2026

From Health Check to Real Functional Test: How We Monitor n8n and Qdrant


We've been using n8n in production for quite some time, both internally and for customer projects. Earlier on this blog, Christian explained how we built an AI powered spam protection workflow with n8n. Regular readers may also know that Gatus is our monitoring solution of choice. One thing was still missing, though. While we monitored whether our infrastructure was reachable, we had no reliable way of verifying that n8n and our Qdrant vector database were actually working as expected. Since both are essential building blocks for many of our AI based workflows, we wanted something more meaningful than a simple uptime check.

What started as "let's add a health check" quickly turned into a deeper look at what production monitoring should really verify.

Step 1: Ready?

Getting Health Checks Right

Most modern applications expose one or more health check endpoints. They are designed for monitoring systems such as Gatus, which periodically request a URL and raise an alert if the expected response changes.

There's a distinction worth making here, one that originated in the Kubernetes world and has since spread well beyond it: liveness versus readiness. A liveness check answers a very simple question: Is the process still running? Nothing more. A readiness check asks something more useful: Is the application currently able to serve requests? A process can be running and still not be ready, for instance because its database connection just dropped.

n8n exposes dedicated endpoints for both checks. /healthz is a liveness endpoint. A HTTP 200 response simply confirms that the process is alive. /healthz/readiness performs additional checks. It only returns HTTP 200 once the database connection has been established and all database migrations have completed. Only then is n8n actually ready to execute workflows. If you're running n8n in production without digging into what's underneath it, the readiness endpoint already gives you a far more meaningful check than its plain name suggests.

That's why we test both endpoints separately, one for /healthz and one for /healthz/readiness.

endpoints:
  - name: n8n-health
    url: "https://n8n.example.com/healthz"
    interval: 5m
    conditions:
      - "[STATUS] == 200"
  - name: n8n-readiness
    url: "https://n8n.example.com/healthz/readiness"
    interval: 5m
    conditions:
      - "[STATUS] == 200"

That's a solid, sensible first step, and it's where most monitoring setups stop. Fair enough, that's exactly what a readiness endpoint is built for.

Step 2: Actually Done?

When "Ready" Doesn't Mean "Working"

For us, step one isn't the finish line, it's the foundation. /healthz/readiness tells nothing about whether the workflow built on top of it is doing what it's supposed to do. A workflow may be fully reachable while still failing halfway through its execution. A node might throw an exception, an AI classification could produce an unexpected result, or an external service might stop responding.

From an infrastructure perspective, everything still looks healthy. From a business perspective, the automation has already failed. In complex automation scenarios involving forms, AI models, vector databases, APIs and email delivery, these are two fundamentally different questions.

What ultimately matters is whether the workflow completed successfully.

Fortunately, n8n exposes its execution history through the REST API. The API returns execution metadata as JSON, allowing us to inspect the most recent workflow runs.

The REST API lets you filter by status and number of executions, but not by a time period. Gatus, on the other hand, doesn't provide date based functions. That creates an interesting challenge. If only the latest execution is checked, a successful run could easily hide an earlier failure that occurred just a few minutes before. Instead, we combine several conditions that together provide a much more reliable picture.

Here's what that looks like in the Gatus config.

endpoints:
  - name: n8n-workflow-spam-protection
    url: "https://n8n.example.com/api/v1/executions?workflowId=123&limit=5"
    headers:
      X-N8N-API-KEY: "${N8N_API_KEY}"
    interval: 5m
    conditions:
      - "[STATUS] == 200"
      - "[CERTIFICATE_EXPIRATION] > 120h"
      - "[BODY].data[0].status == success"
      - '[BODY] != pat(*"status":"error"*)'

Four conditions that together say more than any single one on its own:

  • [STATUS] == 200: the n8n API is responding at all.
  • [CERTIFICATE_EXPIRATION] > 120h: The TLS certificate is still valid for at least another five days. Certificate expirations are easy to overlook and often cause unnecessary outages.
  • [BODY].data[0].status == success: the most recent run of the workflow succeeded.
  • [BODY] != pat(*"status":"error"*): none of the last five runs (fetched via limit=5) contain a "status":"error" anywhere in the response.

The last two conditions look redundant, but they're deliberately not. The first is precise, it looks at exactly the most recent run. The second is broader, it just checks that none of the recent runs contain an error. Besides requiring less configuration than checking every execution individually, it also works regardless of how many execution records are actually returned.

One important difference compared to the health endpoints is that the REST API requires authentication.

Where we draw the line

One question remains intentionally unanswered.

Not every failed execution represents an operational problem. If a workflow gets tested manually during development and fails, that's not an operational problem, but it shows up in the execution history exactly like a real production failure would. n8n does record how each execution was triggered, so separating "tested in the editor" from "ran in production" would be possible in principle. Whether that additional complexity is worth implementing remains to be seen. For now, we're deliberately keeping the monitoring solution simple and will only extend it if practical experience shows that the distinction provides real operational value.

Step 3: A Different Call

Why Databases Need a Different Kind of Check

For n8n, going beyond the readiness check mattered for how the whole system runs. Databases are different. Checking whether the data itself is "correct" quickly becomes application specific and is therefore no longer a health check. For Qdrant we therefore rely on the built-in health endpoints, /healthz and /readyz. The same distinction applies: /healthz only confirms the process is responding, /readyz only returns a HTTP-Code 200 once the collections are actually loaded.

endpoints:
  - name: qdrant-health
    url: "https://qdrant.example.com/healthz"
    interval: 5m
    conditions:
      - "[STATUS] == 200"
  - name: qdrant-readiness
    url: "https://qdrant.example.com/readyz"
    interval: 5m
    conditions:
      - "[STATUS] == 200"

A Practical Observation

Automation that gets built once and then left to run on its own carries essentially the same risk as a server without backups, except nobody notices until the outage has already cost something. If your production environment depends on n8n, AI based workflows or vector databases, these systems deserve the same level of operational monitoring as any other critical infrastructure.

What's Next

For now, we continue observing how the current setup performs in everyday operation. Rather than adding further layers upfront, we prefer to evolve the solution based on real world experience. If distinguishing between production failures and development related executions eventually proves valuable, that will be the next logical step. But only when the need actually arises.

Ingo Schmitt

Fluent in TypoScript, php and sql; knows perl and bash and has very basic knowledge in java. Joined in 1996 and is meanwhile as managing director responsible for development, operation and hosting of our products. Articles in this blog cover technical and sustainable topics. Involved with TYPO3 as chairman of the Business Control Committee (BCC) and organizes the annual TYPO3Camp RheinRuhr.

More posts by this author

Get blog posts as RSS feed

Related posts

  • How we automate container updates on mittwald
  • Intelligent spam protection for TYPO3 forms without CAPTCHA – AI-based solution with n8n
  • When Bot Traffic Suddenly Multiplies by a Thousand

Please feel free to share this article.


Comments

No comments yet.

Write a comment.

I have been informed that the processing of my data is on a voluntary basis and that I can refuse my consent without detrimental consequences for me or withdraw my consent at any time to Marketing Factory Digital GmbH by mail (Erkrather Straße 401, D-40231 Düsseldorf) or e-mail (info@marketing-factory.de).

I understand that the above data will be stored for as long as I wish to be contacted by Marketing Factory. After my revocation my data will be deleted. Further storage may take place in individual cases if this is required by law.

  • Data privacy policy
  • Legal notice

© Marketing Factory Digital GmbH

Alternative text for images is partially generated by AI

Picture Credits
  1. "schwarz weiss kombiinstrument": jannerboy62 / License: Unsplash License