Purpose: Quick checklist to verify retry deduplication is working correctly
Estimated Time: 30 minutes
Role: Backend Engineer / SRE
# Check that getExecutionMetrics() uses deduplication
grep -A 20 "getExecutionMetrics" listener/src/services/scheduled-notification-repository.ts
# Look for: MAX(execution_attempt) in the SQL query
# If not found, the fix is NOT implementedExpected: SQL query with CTE using MAX(execution_attempt)
Status: [ ] VERIFIED
cd listener
npm test -- execution-metrics.test.tsExpected: All 6 tests pass
Status: [ ] PASSED
If tests fail:
- Check database schema is initialized
- Check SQLite3 is installed:
npm list sqlite3 - Review test output for specific errors
# Start the listener service
npm run dev
# In another terminal, check the endpoint exists
curl http://localhost:3000/api/schedule/execution-metricsExpected: JSON response with these fields:
{
"totalNotifications": <number>,
"successfulFirstAttempt": <number>,
"successfulAfterRetry": <number>,
"permanentFailures": <number>,
"totalRetryAttempts": <number>,
"averageRetriesPerNotification": <number>,
"averageSuccessDurationMs": <number>,
"averageFailureDurationMs": <number>
}Status: [ ] VERIFIED
Location: prometheus.yml or Prometheus config
Look for:
scrape_configs:
- job_name: 'notify-chain'
metrics_path: '/metrics' # or any direct database queryAction Required:
- If using
/metrics, verify it usesgetExecutionMetrics()internally - If querying database directly, CHANGE to use API endpoint
- Add scrape endpoint:
/api/schedule/execution-metrics
Status: [ ] AUDITED
Location: /etc/datadog-agent/checks.d/ or Datadog config
Look for:
# BAD: Direct database query
query = "SELECT COUNT(*) FROM notification_execution_log WHERE status = 'SUCCESS'"
# GOOD: API endpoint
url = "http://localhost:3000/api/schedule/execution-metrics"Action Required:
- If querying database, REPLACE with API call
- Use provided example in
docs/MONITORING_INTEGRATION.md
Status: [ ] AUDITED
Location: AWS Lambda functions publishing metrics
Look for:
// BAD: Direct query
const query = "SELECT * FROM notification_execution_log";
// GOOD: API call
const metrics = await fetch('http://notify-chain:3000/api/schedule/execution-metrics');Action Required:
- If querying database, REPLACE with API call
- Use provided Lambda example in
docs/MONITORING_INTEGRATION.md
Status: [ ] AUDITED
Location: Grafana dashboard configs
Look for:
- Direct SQL queries in data sources
- Queries to
notification_execution_logtable
Action Required:
- Change data source to API endpoint
- Or replicate deduplication query (see docs)
Status: [ ] AUDITED
Location: Log parsing/counting queries
Look for:
# BAD: Counts every delivery log message
"Notification delivered successfully" | stats count
# GOOD: Counts state transition logs
"Notification marked as completed" | stats count
Action Required:
- Update log queries to count state transitions, not delivery attempts
- Or switch to using API endpoint
Status: [ ] AUDITED
Location: dashboard/src/services/eventsApi.ts
Check:
// Should have this method:
export const getExecutionMetrics = async () => {
const response = await fetch('/api/schedule/execution-metrics');
return await response.json();
};Status:
- Method exists
- Method is called by dashboard components
- NOT querying database directly
If missing:
# Add to dashboard/src/services/eventsApi.tsSteps:
- Open dashboard in browser
- Create test notification that will retry
- Wait for retries to complete
- Check dashboard counts
Verify:
- Success count matches API response
- Retry count is shown separately
- No inflation of totals
Status: [ ] VERIFIED
curl -X POST http://localhost:3000/api/schedule \
-H "Content-Type: application/json" \
-d '{
"notificationType": "discord",
"targetRecipient": "valid-webhook-url",
"executeAt": "2026-06-20T12:00:00Z",
"maxRetries": 3,
"payload": {"message": "Test immediate success"}
}'
# Wait 1 minute, then check metrics
curl http://localhost:3000/api/schedule/execution-metrics | jqExpected:
totalNotificationsincreases by 1successfulFirstAttemptincreases by 1successfulAfterRetrystays the same
Status: [ ] PASSED
# Use invalid webhook to force retries, then fix it
curl -X POST http://localhost:3000/api/schedule \
-H "Content-Type: application/json" \
-d '{
"notificationType": "discord",
"targetRecipient": "https://discord.com/api/webhooks/INVALID",
"executeAt": "2026-06-20T12:00:00Z",
"maxRetries": 2,
"payload": {"message": "Test retry success"}
}'
# Let it fail twice, then update webhook to valid URL and wait for successExpected:
totalNotificationsincreases by 1 (not 3)successfulAfterRetryincreases by 1totalRetryAttemptsincreases by 2
Status: [ ] PASSED
curl -X POST http://localhost:3000/api/schedule \
-H "Content-Type: application/json" \
-d '{
"notificationType": "discord",
"targetRecipient": "https://discord.com/api/webhooks/INVALID-PERMANENT",
"executeAt": "2026-06-20T12:00:00Z",
"maxRetries": 2,
"payload": {"message": "Test permanent failure"}
}'
# Wait for all retries to exhaust
curl http://localhost:3000/api/schedule/execution-metrics | jqExpected:
totalNotificationsincreases by 1 (not 3)permanentFailuresincreases by 1totalRetryAttemptsincreases by 2
Status: [ ] PASSED
# Count raw execution log entries
sqlite3 listener.db "SELECT COUNT(*) FROM notification_execution_log;"
# Get deduplicated metrics
curl http://localhost:3000/api/schedule/execution-metrics | jq '.totalNotifications'
# The first number should be LARGER than the second
# (because raw logs include retries)Expected: Raw log count > API totalNotifications
Status: [ ] VERIFIED
# Get metrics
curl http://localhost:3000/api/schedule/execution-metrics | jq
# Calculate success rate manually:
# success_rate = (successfulFirstAttempt + successfulAfterRetry) / totalNotifications * 100
# Should be between 0-100%
# Should NOT exceed 100% (would indicate double-counting)Expected: Success rate ≤ 100%
Status: [ ] VERIFIED
Required updates:
- Add API endpoint to internal API documentation
- Document metrics schema (field meanings)
- Add monitoring setup guide link
- Document retry behavior
Locations:
- Internal wiki
- README.md
- API documentation (Swagger/OpenAPI)
Status: [ ] COMPLETED
Action:
- Share
docs/MONITORING_INTEGRATION.mdwith DevOps team - Schedule knowledge-sharing session
- Add to onboarding documentation
Status: [ ] COMPLETED
Prometheus example:
- alert: HighRetryRate
expr: notifications_avg_retries > 0.5
for: 10m
labels:
severity: warning
annotations:
summary: "More than 50% of notifications require retries"Status: [ ] CONFIGURED
Prometheus example:
- alert: LowSuccessRate
expr: 100 * (notifications_success_total / notifications_total) < 90
for: 15m
labels:
severity: critical
annotations:
summary: "Notification success rate below 90%"Status: [ ] CONFIGURED
Questions to answer:
- Were historical metrics affected by double-counting?
- Do past reports need correction?
- Should we re-calculate historical success rates?
Action:
# Run deduplication query against historical data
sqlite3 listener.db < historical_metrics_query.sqlStatus: [ ] AUDITED
Scenario: Create 10 notifications with mixed outcomes
- 4 immediate successes
- 3 successes after 1 retry
- 2 successes after 2 retries
- 1 permanent failure after 3 attempts
Expected totals:
totalNotifications: 10successfulFirstAttempt: 4successfulAfterRetry: 5permanentFailures: 1totalRetryAttempts: 9 (3 + 4 + 2)
Status: [ ] PASSED
Verification by:
- Backend Engineer: _____________________ Date: _______
- SRE/DevOps: _____________________ Date: _______
- QA Engineer: _____________________ Date: _______
Issues Found: _________________________________________________
Follow-up Required: [ ] Yes [ ] No
Notes:
If metrics still show double-counting:
- Verify API endpoint is being used (check network traffic)
- Check database query logs for direct
notification_execution_logqueries - Review Prometheus/Datadog configuration files
- Check dashboard network requests (browser dev tools)
- Confirm tests are passing
If tests fail:
- Check database schema is properly initialized
- Verify sqlite3 package is installed
- Review error messages for specific table/column issues
- Check file permissions on test database directory
If API returns errors:
- Check application logs for database connection issues
- Verify database file exists and is readable
- Check for SQL syntax errors in logs
- Confirm schema migrations have run
- Detailed Analysis:
TELEMETRY_BUG_ANALYSIS.md - Monitoring Guide:
docs/MONITORING_INTEGRATION.md - Quick Summary:
EXECUTIVE_SUMMARY.md - Test Suite:
listener/src/services/execution-metrics.test.ts - Additional Tests:
listener/src/services/retry-deduplication.test.ts
Checklist Complete: _____ / 22 items verified
Ready for Production: [ ] Yes [ ] No
Date Completed: _________________