Monitoring Setup
Two layers: application health (errors, user behavior) and operational health
(are the queues draining, is the database keeping up). An app with clean Sentry but a
queue backing up or a table scan on every request is still failing its users — cover
both.
When to Use
- Need to set up error tracking (Sentry)
- Want to configure Google Analytics
- Need monitoring for production applications
- Want to track application errors and user behavior
- Need operational signals: queue depth, slow queries, connection saturation, and
alerts on them
Sentry Setup
NestJS Backend
- Install:
bun add @sentry/node @sentry/profiling-node
- Initialize in
main.ts before app creation
- Configure DSN via
SENTRY_DSN environment variable
- Set appropriate sample rates for production
Next.js Frontend
- Install:
bun add @sentry/nextjs
- Run:
bunx @sentry/wizard@latest -i nextjs
- Configure client/server/edge configs
- Set
NEXT_PUBLIC_SENTRY_DSN for client-side
Google Analytics Setup
Next.js Setup
- Add Google Analytics script to root layout
- Use
NEXT_PUBLIC_GA_MEASUREMENT_ID (format: G-XXXXXXXXXX)
- Create analytics utility functions for event tracking
- Set up page view tracking
Common Events
- User signup/login
- Purchases/conversions
- Feature usage
- Custom business events
Operational Monitoring
Application errors tell you what threw; operational signals tell you what is quietly
degrading. Instrument the three that take a product down under load.
BullMQ queue depth
A queue that fills faster than it drains is an outage in slow motion — no error fires
until jobs time out.
- Track per queue: waiting (backlog), active, failed, and completed
rate.
Queue.getJobCounts() exposes these; scrape them on an interval or via
bullmq-prometheus.
- The signal that matters is trend: waiting climbing while completed is flat means
workers cannot keep up (scale workers or the Redis connection).
- Watch the dead-letter / failed set — jobs exhausting retries are silent data loss.
Postgres slow queries & connections
- Enable
pg_stat_statements; surface the top queries by total time and by mean time.
A query that is individually fast but runs 10k×/min is the real cost.
- Log queries over a threshold (
log_min_duration_statement) and alert on new
entrants — a slow query usually means a missing index or an N+1.
- Track connection saturation (
active / max_connections). Near the ceiling on
serverless means the pooler is undersized — see postgres-ops.
Redis
- Memory usage vs
maxmemory, eviction rate, and command latency. Evictions mean the
cache is too small and hit-rate is silently dropping.
Alerting
Instrumentation no one looks at is not monitoring. For each signal above, define a
threshold and route it somewhere a human sees at 3am (PagerDuty, Opsgenie, a Slack
channel that pages). Alert on the leading indicator (queue waiting climbing,
connections near max) not just the lagging one (jobs already timing out, 500s
already served). Every alert names the runbook step to take, or it is just noise.
Best Practices
- Use different DSNs for dev/prod
- Set appropriate sample rates
- Respect user privacy (GDPR/CCPA)
- Don't track sensitive data
- Alert on leading operational indicators, not only on errors after the fact
- Every alert links to a runbook action — no orphan alerts
Integration
This skill integrates with /monitoring-setup command for automated setup workflows.
Pairs with postgres-ops (pooling, DR) and nestjs-queue-architect (queue design).
1---
2name: monitoring-setup
3description: Sets up production monitoring for NestJS and Next.js apps — Sentry error tracking, Google Analytics, and operational signals (BullMQ queue depth, Postgres slow queries, connection saturation) with alerts on each. Activates when users need error tracking, production monitoring, analytics, queue/database observability, or alerting on operational health.
4metadata:
5 version: "1.1.0"
6 tags: "monitoring, sentry, analytics, observability, alerting, bullmq, postgres"
7---
8
9# Monitoring Setup
10
11Two layers: **application** health (errors, user behavior) and **operational** health
12(are the queues draining, is the database keeping up). An app with clean Sentry but a
13queue backing up or a table scan on every request is still failing its users — cover
14both.
15
16## When to Use
17
18- Need to set up error tracking (Sentry)
19- Want to configure Google Analytics
20- Need monitoring for production applications
21- Want to track application errors and user behavior
22- Need operational signals: queue depth, slow queries, connection saturation, and
23 alerts on them
24
25## Sentry Setup
26
27### NestJS Backend
28
291. Install: `bun add @sentry/node @sentry/profiling-node`
302. Initialize in `main.ts` before app creation
313. Configure DSN via `SENTRY_DSN` environment variable
324. Set appropriate sample rates for production
33
34### Next.js Frontend
35
361. Install: `bun add @sentry/nextjs`
372. Run: `bunx @sentry/wizard@latest -i nextjs`
383. Configure client/server/edge configs
394. Set `NEXT_PUBLIC_SENTRY_DSN` for client-side
40
41## Google Analytics Setup
42
43### Next.js Setup
44
451. Add Google Analytics script to root layout
462. Use `NEXT_PUBLIC_GA_MEASUREMENT_ID` (format: G-XXXXXXXXXX)
473. Create analytics utility functions for event tracking
484. Set up page view tracking
49
50### Common Events
51
52- User signup/login
53- Purchases/conversions
54- Feature usage
55- Custom business events
56
57## Operational Monitoring
58
59Application errors tell you what threw; operational signals tell you what is quietly
60degrading. Instrument the three that take a product down under load.
61
62### BullMQ queue depth
63
64A queue that fills faster than it drains is an outage in slow motion — no error fires
65until jobs time out.
66
67- Track per queue: **waiting** (backlog), **active**, **failed**, and **completed
68 rate**. `Queue.getJobCounts()` exposes these; scrape them on an interval or via
69 `bullmq-prometheus`.
70- The signal that matters is **trend**: waiting climbing while completed is flat means
71 workers cannot keep up (scale workers or the Redis connection).
72- Watch the **dead-letter / failed** set — jobs exhausting retries are silent data loss.
73
74### Postgres slow queries & connections
75
76- Enable `pg_stat_statements`; surface the top queries by total time and by mean time.
77 A query that is individually fast but runs 10k×/min is the real cost.
78- Log queries over a threshold (`log_min_duration_statement`) and alert on new
79 entrants — a slow query usually means a missing index or an N+1.
80- Track **connection saturation** (`active / max_connections`). Near the ceiling on
81 serverless means the pooler is undersized — see `postgres-ops`.
82
83### Redis
84
85- Memory usage vs `maxmemory`, eviction rate, and command latency. Evictions mean the
86 cache is too small and hit-rate is silently dropping.
87
88## Alerting
89
90Instrumentation no one looks at is not monitoring. For each signal above, define a
91threshold and route it somewhere a human sees at 3am (PagerDuty, Opsgenie, a Slack
92channel that pages). Alert on the **leading** indicator (queue waiting climbing,
93connections near max) not just the **lagging** one (jobs already timing out, 500s
94already served). Every alert names the runbook step to take, or it is just noise.
95
96## Best Practices
97
98- Use different DSNs for dev/prod
99- Set appropriate sample rates
100- Respect user privacy (GDPR/CCPA)
101- Don't track sensitive data
102- Alert on leading operational indicators, not only on errors after the fact
103- Every alert links to a runbook action — no orphan alerts
104
105## Integration
106
107This skill integrates with `/monitoring-setup` command for automated setup workflows.
108Pairs with `postgres-ops` (pooling, DR) and `nestjs-queue-architect` (queue design).