From 4b5495fb498a471e48cad65974cfb35a9101c747 Mon Sep 17 00:00:00 2001 From: Tyler Koenig Date: Sat, 23 May 2026 20:05:30 -0400 Subject: [PATCH] fix(monitor): add jitter to check intervals and stagger startup Monitors with the same interval no longer fire simultaneously. Each tick adds up to 10% random jitter. Initial checks stagger over 0-3s to avoid thundering herd on startup. --- internal/monitor/monitor.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/internal/monitor/monitor.go b/internal/monitor/monitor.go index 1029d1c..bcd4371 100644 --- a/internal/monitor/monitor.go +++ b/internal/monitor/monitor.go @@ -7,6 +7,7 @@ import ( "go-upkeep/internal/alert" "go-upkeep/internal/models" "go-upkeep/internal/store" + "math/rand/v2" "net/http" "sync" "time" @@ -277,6 +278,14 @@ func (e *Engine) ToggleSitePause(id int) bool { } func (e *Engine) monitorRoutine(ctx context.Context, id int) { + // Stagger initial check to avoid thundering herd on startup + stagger := time.Duration(rand.IntN(3000)) * time.Millisecond + select { + case <-time.After(stagger): + case <-ctx.Done(): + return + } + e.checkByID(id) for { select { @@ -314,8 +323,9 @@ func (e *Engine) monitorRoutine(ctx context.Context, id int) { if interval < 5 { interval = 5 } + jitter := time.Duration(rand.IntN(interval*100)) * time.Millisecond select { - case <-time.After(time.Duration(interval) * time.Second): + case <-time.After(time.Duration(interval)*time.Second + jitter): case <-ctx.Done(): return }