Add 5 wiki articles from 2026-04-17/18 work
- ghost-smtp-mailgun-setup: two-system email config (newsletter API + transactional SMTP) - firewalld-fleet-hardening: Fedora fleet firewall audit-and-harden pattern with Ansible - clamav-fleet-deployment: fleet deployment with nice/ionice throttling + quarantine - ansible-check-mode-false-positives: when: not ansible_check_mode guard for verify/assert tasks - ghost-emailanalytics-lag-warning: submitted status, lag counter, fetchMissing skip explained
This commit is contained in:
106
05-troubleshooting/ghost-emailanalytics-lag-warning.md
Normal file
106
05-troubleshooting/ghost-emailanalytics-lag-warning.md
Normal file
@@ -0,0 +1,106 @@
|
||||
---
|
||||
title: Ghost EmailAnalytics Lag Warning — What It Means and When to Worry
|
||||
domain: selfhosting
|
||||
category: troubleshooting
|
||||
tags:
|
||||
- ghost
|
||||
- email
|
||||
- mailgun
|
||||
- emailanalytics
|
||||
- docker
|
||||
- troubleshooting
|
||||
status: published
|
||||
created: 2026-04-18
|
||||
updated: 2026-04-18T11:13
|
||||
---
|
||||
# Ghost EmailAnalytics Lag Warning — What It Means and When to Worry
|
||||
|
||||
## The Warning
|
||||
|
||||
Ghost logs a recurring warning every 5 minutes when its EmailAnalytics job falls behind:
|
||||
|
||||
```
|
||||
WARN [EmailAnalytics] Opened events processing is 738.0 minutes behind (threshold: 30)
|
||||
```
|
||||
|
||||
This is followed by:
|
||||
|
||||
```
|
||||
INFO [EmailAnalytics] Job complete - No events
|
||||
INFO [EmailAnalytics] Skipping fetchMissing because end (...) is before begin (...)
|
||||
```
|
||||
|
||||
The counter increments by 5 with every cycle. On a small newsletter, it will grow indefinitely and never reset on its own — until a subscriber opens an email or a new newsletter is sent.
|
||||
|
||||
## Why It Happens
|
||||
|
||||
Ghost's EmailAnalytics polls Mailgun every 5 minutes for new "opened" events. The cursor is anchored to the timestamp of the last email delivery. If no new opened events arrive from Mailgun, the cursor doesn't advance and the lag counter grows.
|
||||
|
||||
This is **expected behavior** when:
|
||||
- All subscribers have already opened (their open was recorded)
|
||||
- One or more subscribers have not opened the email and haven't opened any subsequent emails
|
||||
- There are no new emails to send
|
||||
|
||||
The lag counter = time since the last opened event was recorded, not time since the last email was sent.
|
||||
|
||||
## The `fetchMissing end == begin` Skip
|
||||
|
||||
```
|
||||
INFO [EmailAnalytics] Skipping fetchMissing because end (Fri Apr 17 2026 15:44:57 ...) is before begin (Fri Apr 17 2026 15:44:57 ...)
|
||||
```
|
||||
|
||||
This fires when the cursor window collapses to zero width — the start and end of the query window are identical. Ghost's guard clause skips a nonsensical zero-width Mailgun API call. This is not a bug or data loss — it's a safety check.
|
||||
|
||||
## What `status: submitted` Means
|
||||
|
||||
In Ghost's `emails` database table, all successfully sent newsletters show `status: submitted`. This is the normal terminal state after Ghost hands the email batch off to Mailgun. There is no `status: sent` — `submitted` = success.
|
||||
|
||||
You can verify delivery success by checking the counts:
|
||||
|
||||
```bash
|
||||
docker exec <db-container> mysql -u root -p<password> ghost \
|
||||
-e "SELECT subject, status, email_count, delivered_count, opened_count, failed_count FROM emails ORDER BY created_at DESC LIMIT 5;"
|
||||
```
|
||||
|
||||
A healthy result: `email_count == delivered_count`, `failed_count == 0`, regardless of `opened_count`.
|
||||
|
||||
## When to Actually Worry
|
||||
|
||||
The lag warning is **benign** in these cases:
|
||||
- `delivered_count == email_count` (all emails delivered)
|
||||
- `failed_count == 0`
|
||||
- Mailgun domain state is active
|
||||
- The warning appeared after a successful send and has been growing since
|
||||
|
||||
Investigate further if:
|
||||
- `delivered_count < email_count` — some emails never left Mailgun
|
||||
- `failed_count > 0` — delivery failures
|
||||
- The warning appeared immediately after a Ghost upgrade or Mailgun credential change
|
||||
- Mailgun Events API shows 0 delivered events (not just 0 opened events) for the send window
|
||||
|
||||
## Checking Mailgun Directly
|
||||
|
||||
If you suspect the lag reflects a real delivery problem, query Mailgun's Events API:
|
||||
|
||||
```bash
|
||||
# Check for delivered events in the send window
|
||||
curl -s --user "api:<your-mailgun-api-key>" \
|
||||
"https://api.mailgun.net/v3/<your-domain>/events?event=delivered&begin=<RFC2822-timestamp>&limit=10" \
|
||||
| python3 -m json.tool | grep -E "event|recipient|timestamp" | head -30
|
||||
```
|
||||
|
||||
If delivered events appear for your subscribers, Mailgun is working and the lag warning is purely cosmetic.
|
||||
|
||||
## How It Resolves
|
||||
|
||||
The lag warning self-resolves when:
|
||||
1. **A subscriber opens an email** — Mailgun returns an "opened" event, the cursor advances, lag resets
|
||||
2. **A new newsletter is sent** — the send triggers a fresh analytics cycle, cursor jumps forward
|
||||
3. **Manually resetting the cursor** — possible via direct DB update, but not recommended unless you understand the implications for analytics continuity
|
||||
|
||||
For small newsletters (2–10 subscribers) where one subscriber consistently doesn't open emails, the warning is permanent background noise between sends. It does not indicate data loss or misconfiguration.
|
||||
|
||||
## See Also
|
||||
|
||||
- [ghost-smtp-mailgun-setup](../02-selfhosting/services/ghost-smtp-mailgun-setup.md)
|
||||
- [debugging-broken-docker-containers](../02-selfhosting/docker/debugging-broken-docker-containers.md)
|
||||
Reference in New Issue
Block a user