[{"data":1,"prerenderedAt":491},["ShallowReactive",2],{"docs-\u002Fdocs\u002Fheartbeats":3},{"id":4,"title":5,"body":6,"description":483,"extension":484,"meta":485,"navigation":486,"path":487,"seo":488,"stem":489,"__hash__":490},"docs\u002Fdocs\u002F11.heartbeats.md","Heartbeats",{"type":7,"value":8,"toc":468},"minimark",[9,13,17,20,26,31,56,60,113,117,154,158,163,166,170,177,187,190,252,256,259,262,266,269,275,290,294,300,343,350,355,402,407,424,428,431,452,456,464],[10,11,5],"h1",{"id":12},"heartbeats",[14,15,16],"p",{},"A heartbeat is an inverted monitor: instead of Vantaj reaching out to check something, your job reaches in to say \"I ran successfully.\" If the ping stops arriving, Vantaj alerts you.",[14,18,19],{},"This makes heartbeats the right tool for things that can fail silently — a cron job that crashes before completing, a backup script that never starts because the server rebooted, a worker process that stopped without raising an error.",[21,22],"img",{"src":23,"alt":24,"style":25},"\u002Fdocs\u002Fheartbeats.png","Heartbeats list showing job status, ping URLs, and integration examples","border-radius:12px;width:100%;margin:1rem 0;",[27,28,30],"h2",{"id":29},"how-it-works","How it works",[32,33,34,38,41,44],"ol",{},[35,36,37],"li",{},"You create a heartbeat and set how often your job is expected to run",[35,39,40],{},"Vantaj gives you a unique ping URL",[35,42,43],{},"Your job calls that URL at the end of each successful run",[35,45,46,47,51,52],{},"Vantaj checks every minute: if no ping has arrived within ",[48,49,50],"code",{},"interval + grace",", the heartbeat is marked ",[53,54,55],"strong",{},"missed",[27,57,59],{"id":58},"status-values","Status values",[61,62,63,76],"table",{},[64,65,66],"thead",{},[67,68,69,73],"tr",{},[70,71,72],"th",{},"Status",[70,74,75],{},"Meaning",[77,78,79,90,103],"tbody",{},[67,80,81,87],{},[82,83,84],"td",{},[48,85,86],{},"Healthy",[82,88,89],{},"A ping arrived within the expected window",[67,91,92,97],{},[82,93,94],{},[48,95,96],{},"Missed",[82,98,99,100],{},"No ping arrived within ",[48,101,102],{},"interval + grace period",[67,104,105,110],{},[82,106,107],{},[48,108,109],{},"Waiting",[82,111,112],{},"Heartbeat was just created and no ping has been received yet",[27,114,116],{"id":115},"creating-a-heartbeat","Creating a heartbeat",[32,118,119,125,131,142,145,148],{},[35,120,121,122,124],{},"Go to ",[53,123,5],{}," in the left navigation",[35,126,127,128],{},"Click ",[53,129,130],{},"New heartbeat",[35,132,133,134,137,138,141],{},"Give it a name (e.g. ",[48,135,136],{},"Nightly backup",", ",[48,139,140],{},"Invoice sync",")",[35,143,144],{},"Set the schedule type and expected interval",[35,146,147],{},"Set a grace period",[35,149,127,150,153],{},[53,151,152],{},"Create heartbeat"," — you'll see the ping URL immediately",[27,155,157],{"id":156},"schedule-types","Schedule types",[159,160,162],"h3",{"id":161},"interval","Interval",[14,164,165],{},"Choose a preset interval — every 5 minutes, every hour, every day, and so on. Vantaj expects a ping every N minutes, plus the grace period.",[159,167,169],{"id":168},"cron","Cron",[14,171,172,173,176],{},"Enter a cron expression (e.g. ",[48,174,175],{},"0 3 * * *"," for 3 AM daily) and select a timezone. Use this when your job runs at a specific time of day rather than on a rolling interval.",[178,179,184],"pre",{"className":180,"code":182,"language":183},[181],"language-text","minute · hour · day-of-month · month · day-of-week\n","text",[48,185,182],{"__ignoreMap":186},"",[14,188,189],{},"Common examples:",[61,191,192,201],{},[64,193,194],{},[67,195,196,199],{},[70,197,198],{},"Expression",[70,200,75],{},[77,202,203,213,223,232,242],{},[67,204,205,210],{},[82,206,207],{},[48,208,209],{},"* * * * *",[82,211,212],{},"Every minute",[67,214,215,220],{},[82,216,217],{},[48,218,219],{},"0 * * * *",[82,221,222],{},"Every hour",[67,224,225,229],{},[82,226,227],{},[48,228,175],{},[82,230,231],{},"Every day at 3 AM",[67,233,234,239],{},[82,235,236],{},[48,237,238],{},"0 9 * * 1",[82,240,241],{},"Every Monday at 9 AM",[67,243,244,249],{},[82,245,246],{},[48,247,248],{},"0 0 1 * *",[82,250,251],{},"First day of every month",[27,253,255],{"id":254},"grace-period","Grace period",[14,257,258],{},"The grace period is extra time Vantaj waits after the expected interval before marking a heartbeat as missed. Use it to absorb legitimate delays — a job that usually runs in 30 seconds but occasionally takes 2 minutes under load.",[14,260,261],{},"For example, with a 1-hour interval and 5-minute grace, a heartbeat is marked missed only if no ping arrives within 1 hour and 5 minutes of the previous ping.",[27,263,265],{"id":264},"the-ping-url","The ping URL",[14,267,268],{},"Each heartbeat has a unique URL like:",[178,270,273],{"className":271,"code":272,"language":183},[181],"https:\u002F\u002Fapp.vantaj.co\u002Fapi\u002Fhb\u002F\u003Ctoken>\n",[48,274,272],{"__ignoreMap":186},[14,276,277,278,281,282,285,286,289],{},"Call it with ",[48,279,280],{},"GET"," or ",[48,283,284],{},"POST"," — both work. Call it ",[53,287,288],{},"after"," your job completes successfully, not before. If your job fails partway through, don't call it — the missed ping is the signal.",[27,291,293],{"id":292},"integration-examples","Integration examples",[14,295,296,299],{},[53,297,298],{},"Shell \u002F cron"," — append to your cron command:",[178,301,305],{"className":302,"code":303,"language":304,"meta":186,"style":186},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","your-job && curl -fsS -m 10 --retry 3 https:\u002F\u002Fapp.vantaj.co\u002Fapi\u002Fhb\u002FYOUR_TOKEN\n","bash",[48,306,307],{"__ignoreMap":186},[308,309,312,316,320,323,327,330,334,337,340],"span",{"class":310,"line":311},"line",1,[308,313,315],{"class":314},"sBMFI","your-job",[308,317,319],{"class":318},"sMK4o"," &&",[308,321,322],{"class":314}," curl",[308,324,326],{"class":325},"sfazB"," -fsS",[308,328,329],{"class":325}," -m",[308,331,333],{"class":332},"sbssI"," 10",[308,335,336],{"class":325}," --retry",[308,338,339],{"class":332}," 3",[308,341,342],{"class":325}," https:\u002F\u002Fapp.vantaj.co\u002Fapi\u002Fhb\u002FYOUR_TOKEN\n",[14,344,345,346,349],{},"The ",[48,347,348],{},"&&"," ensures the ping only fires if the job exits with code 0.",[14,351,352],{},[53,353,354],{},"Node.js:",[178,356,360],{"className":357,"code":358,"language":359,"meta":186,"style":186},"language-js shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","await runYourJob();\nawait fetch('https:\u002F\u002Fapp.vantaj.co\u002Fapi\u002Fhb\u002FYOUR_TOKEN');\n","js",[48,361,362,379],{"__ignoreMap":186},[308,363,364,368,372,376],{"class":310,"line":311},[308,365,367],{"class":366},"s7zQu","await",[308,369,371],{"class":370},"s2Zo4"," runYourJob",[308,373,375],{"class":374},"sTEyZ","()",[308,377,378],{"class":318},";\n",[308,380,382,384,387,390,393,396,398,400],{"class":310,"line":381},2,[308,383,367],{"class":366},[308,385,386],{"class":370}," fetch",[308,388,389],{"class":374},"(",[308,391,392],{"class":318},"'",[308,394,395],{"class":325},"https:\u002F\u002Fapp.vantaj.co\u002Fapi\u002Fhb\u002FYOUR_TOKEN",[308,397,392],{"class":318},[308,399,141],{"class":374},[308,401,378],{"class":318},[14,403,404],{},[53,405,406],{},"Python:",[178,408,412],{"className":409,"code":410,"language":411,"meta":186,"style":186},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","run_your_job()\nrequests.get('https:\u002F\u002Fapp.vantaj.co\u002Fapi\u002Fhb\u002FYOUR_TOKEN', timeout=10)\n","python",[48,413,414,419],{"__ignoreMap":186},[308,415,416],{"class":310,"line":311},[308,417,418],{},"run_your_job()\n",[308,420,421],{"class":310,"line":381},[308,422,423],{},"requests.get('https:\u002F\u002Fapp.vantaj.co\u002Fapi\u002Fhb\u002FYOUR_TOKEN', timeout=10)\n",[27,425,427],{"id":426},"ping-history","Ping history",[14,429,430],{},"The heartbeat detail page shows:",[432,433,434,440,446],"ul",{},[35,435,436,439],{},[53,437,438],{},"Last ping"," — how long ago the most recent ping arrived, updating live",[35,441,442,445],{},[53,443,444],{},"Last 24 hours"," — hourly bar chart of ping activity",[35,447,448,451],{},[53,449,450],{},"Recent pings"," — a log of the last 20 pings with timestamp, method, user-agent, and IP",[27,453,455],{"id":454},"what-heartbeats-dont-replace","What heartbeats don't replace",[14,457,458,459,463],{},"Heartbeats monitor ",[460,461,462],"em",{},"whether"," a job ran — not whether it ran correctly. If your backup script runs but backs up 0 bytes, it will still ping successfully. Combine heartbeats with application-level checks (e.g. verify the backup file exists and has a non-zero size before calling the ping URL) for deeper coverage.",[465,466,467],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}",{"title":186,"searchDepth":381,"depth":381,"links":469},[470,471,472,473,478,479,480,481,482],{"id":29,"depth":381,"text":30},{"id":58,"depth":381,"text":59},{"id":115,"depth":381,"text":116},{"id":156,"depth":381,"text":157,"children":474},[475,477],{"id":161,"depth":476,"text":162},3,{"id":168,"depth":476,"text":169},{"id":254,"depth":381,"text":255},{"id":264,"depth":381,"text":265},{"id":292,"depth":381,"text":293},{"id":426,"depth":381,"text":427},{"id":454,"depth":381,"text":455},"Monitor scheduled jobs and background workers by expecting regular pings","md",{},true,"\u002Fdocs\u002Fheartbeats",{"title":5,"description":483},"docs\u002F11.heartbeats","TakmazZvtRVFEeX73IN7jzXkqGvEqPYgwyMePUWCkDE",1780583796959]