[{"data":1,"prerenderedAt":1482},["ShallowReactive",2],{"\u002Fblog\u002Fuptime-monitoring-vercel":3},{"id":4,"title":5,"author":6,"body":8,"category":1472,"date":1473,"description":1474,"extension":1475,"image":1476,"lastUpdated":1476,"meta":1477,"navigation":224,"path":1478,"readingTime":318,"seo":1479,"stem":1480,"__hash__":1481},"blog\u002Fblog\u002Fuptime-monitoring-vercel.md","Uptime Monitoring for Vercel: What Works, What Doesn't, and How to Set It Up",{"name":7},"Vantaj Team",{"type":9,"value":10,"toc":1441},"minimark",[11,15,18,21,24,29,32,146,154,158,163,170,515,518,522,525,542,553,557,560,564,567,668,671,674,678,682,688,692,695,703,707,710,724,727,731,734,736,740,744,747,755,758,762,765,768,772,783,787,790,792,796,800,803,876,879,883,886,890,896,899,901,905,908,917,1135,1143,1281,1283,1287,1290,1364,1367,1384,1387,1398,1400,1404,1407,1434,1437],[12,13,14],"p",{},"Vercel is excellent at deploying and hosting Next.js applications. It handles global CDN distribution, serverless function scaling, edge caching, and preview deployments with almost no configuration.",[12,16,17],{},"What Vercel doesn't include: uptime monitoring.",[12,19,20],{},"If your production app on Vercel goes down - due to a serverless function error, an edge middleware crash, an upstream database failure, or a Vercel platform incident - you won't know until a user reports it or you happen to open your dashboard.",[12,22,23],{},"This guide covers how to set up meaningful uptime monitoring for Vercel deployments, what to actually monitor (it's more than just the homepage), and what most monitoring tools miss about serverless architectures.",[25,26,28],"h2",{"id":27},"what-down-means-on-vercel","What \"Down\" Means on Vercel",[12,30,31],{},"On a traditional server, \"down\" is simple: the server isn't responding. On Vercel, there are several distinct failure modes:",[33,34,35,51],"table",{},[36,37,38],"thead",{},[39,40,41,45,48],"tr",{},[42,43,44],"th",{},"Failure type",[42,46,47],{},"What happens",[42,49,50],{},"Detectable by HTTP monitoring?",[52,53,54,69,82,94,107,120,133],"tbody",{},[39,55,56,63,66],{},[57,58,59],"td",{},[60,61,62],"strong",{},"Vercel platform outage",[57,64,65],{},"All requests fail or time out",[57,67,68],{},"✅ Yes",[39,70,71,76,79],{},[57,72,73],{},[60,74,75],{},"Serverless function crash",[57,77,78],{},"Function returns 500 error",[57,80,81],{},"✅ Yes (if you monitor the right endpoint)",[39,83,84,89,92],{},[57,85,86],{},[60,87,88],{},"Edge middleware error",[57,90,91],{},"Requests hang or return 500 before reaching your app",[57,93,68],{},[39,95,96,101,104],{},[57,97,98],{},[60,99,100],{},"Build\u002Fdeployment failure",[57,102,103],{},"New deployments fail silently, traffic routes to last working build",[57,105,106],{},"❌ No (not detectable by HTTP monitoring alone)",[39,108,109,114,117],{},[57,110,111],{},[60,112,113],{},"Database connection failure",[57,115,116],{},"API routes that need DB return 500, static pages still load fine",[57,118,119],{},"✅ Only if you monitor API routes specifically",[39,121,122,127,130],{},[57,123,124],{},[60,125,126],{},"Third-party API dependency failure",[57,128,129],{},"Your code returns 500 for affected features",[57,131,132],{},"✅ Only if you test the specific affected endpoint",[39,134,135,140,143],{},[57,136,137],{},[60,138,139],{},"Edge cache serving stale content",[57,141,142],{},"The site \"works\" but serves outdated data",[57,144,145],{},"❌ Requires content validation, not just HTTP checks",[12,147,148,149,153],{},"The implication: monitoring ",[150,151,152],"code",{},"https:\u002F\u002Fyourapp.com"," with an HTTP check tells you if the homepage loads. It tells you almost nothing about whether your API routes, authentication, checkout flow, or database-dependent features are functioning.",[25,155,157],{"id":156},"what-to-actually-monitor-on-vercel","What to Actually Monitor on Vercel",[159,160,162],"h3",{"id":161},"_1-a-health-check-endpoint-not-the-homepage","1. A health check endpoint (not the homepage)",[12,164,165,166,169],{},"Create a dedicated ",[150,167,168],{},"\u002Fapi\u002Fhealth"," route in your Next.js app that actually tests your dependencies:",[171,172,177],"pre",{"className":173,"code":174,"language":175,"meta":176,"style":176},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F app\u002Fapi\u002Fhealth\u002Froute.ts\nimport { db } from '@\u002Flib\u002Fdb'\n\nexport async function GET() {\n  try {\n    \u002F\u002F Test your actual database connection\n    await db.execute('SELECT 1')\n\n    return Response.json({\n      status: 'ok',\n      timestamp: new Date().toISOString(),\n      checks: {\n        database: 'ok',\n      }\n    })\n  } catch (error) {\n    return Response.json(\n      {\n        status: 'error',\n        error: 'Database connection failed',\n      },\n      { status: 503 }\n    )\n  }\n}\n","typescript","",[150,178,179,188,219,226,249,257,263,292,297,316,335,360,370,386,392,400,420,434,440,456,473,479,497,503,509],{"__ignoreMap":176},[180,181,184],"span",{"class":182,"line":183},"line",1,[180,185,187],{"class":186},"sHwdD","\u002F\u002F app\u002Fapi\u002Fhealth\u002Froute.ts\n",[180,189,191,195,199,203,206,209,212,216],{"class":182,"line":190},2,[180,192,194],{"class":193},"s7zQu","import",[180,196,198],{"class":197},"sMK4o"," {",[180,200,202],{"class":201},"sTEyZ"," db",[180,204,205],{"class":197}," }",[180,207,208],{"class":193}," from",[180,210,211],{"class":197}," '",[180,213,215],{"class":214},"sfazB","@\u002Flib\u002Fdb",[180,217,218],{"class":197},"'\n",[180,220,222],{"class":182,"line":221},3,[180,223,225],{"emptyLinePlaceholder":224},true,"\n",[180,227,229,232,236,239,243,246],{"class":182,"line":228},4,[180,230,231],{"class":193},"export",[180,233,235],{"class":234},"spNyl"," async",[180,237,238],{"class":234}," function",[180,240,242],{"class":241},"s2Zo4"," GET",[180,244,245],{"class":197},"()",[180,247,248],{"class":197}," {\n",[180,250,252,255],{"class":182,"line":251},5,[180,253,254],{"class":193},"  try",[180,256,248],{"class":197},[180,258,260],{"class":182,"line":259},6,[180,261,262],{"class":186},"    \u002F\u002F Test your actual database connection\n",[180,264,266,269,271,274,277,281,284,287,289],{"class":182,"line":265},7,[180,267,268],{"class":193},"    await",[180,270,202],{"class":201},[180,272,273],{"class":197},".",[180,275,276],{"class":241},"execute",[180,278,280],{"class":279},"swJcz","(",[180,282,283],{"class":197},"'",[180,285,286],{"class":214},"SELECT 1",[180,288,283],{"class":197},[180,290,291],{"class":279},")\n",[180,293,295],{"class":182,"line":294},8,[180,296,225],{"emptyLinePlaceholder":224},[180,298,300,303,306,308,311,313],{"class":182,"line":299},9,[180,301,302],{"class":193},"    return",[180,304,305],{"class":201}," Response",[180,307,273],{"class":197},[180,309,310],{"class":241},"json",[180,312,280],{"class":279},[180,314,315],{"class":197},"{\n",[180,317,319,322,325,327,330,332],{"class":182,"line":318},10,[180,320,321],{"class":279},"      status",[180,323,324],{"class":197},":",[180,326,211],{"class":197},[180,328,329],{"class":214},"ok",[180,331,283],{"class":197},[180,333,334],{"class":197},",\n",[180,336,338,341,343,346,349,351,353,356,358],{"class":182,"line":337},11,[180,339,340],{"class":279},"      timestamp",[180,342,324],{"class":197},[180,344,345],{"class":197}," new",[180,347,348],{"class":241}," Date",[180,350,245],{"class":279},[180,352,273],{"class":197},[180,354,355],{"class":241},"toISOString",[180,357,245],{"class":279},[180,359,334],{"class":197},[180,361,363,366,368],{"class":182,"line":362},12,[180,364,365],{"class":279},"      checks",[180,367,324],{"class":197},[180,369,248],{"class":197},[180,371,373,376,378,380,382,384],{"class":182,"line":372},13,[180,374,375],{"class":279},"        database",[180,377,324],{"class":197},[180,379,211],{"class":197},[180,381,329],{"class":214},[180,383,283],{"class":197},[180,385,334],{"class":197},[180,387,389],{"class":182,"line":388},14,[180,390,391],{"class":197},"      }\n",[180,393,395,398],{"class":182,"line":394},15,[180,396,397],{"class":197},"    }",[180,399,291],{"class":279},[180,401,403,406,409,412,415,418],{"class":182,"line":402},16,[180,404,405],{"class":197},"  }",[180,407,408],{"class":193}," catch",[180,410,411],{"class":279}," (",[180,413,414],{"class":201},"error",[180,416,417],{"class":279},") ",[180,419,315],{"class":197},[180,421,423,425,427,429,431],{"class":182,"line":422},17,[180,424,302],{"class":193},[180,426,305],{"class":201},[180,428,273],{"class":197},[180,430,310],{"class":241},[180,432,433],{"class":279},"(\n",[180,435,437],{"class":182,"line":436},18,[180,438,439],{"class":197},"      {\n",[180,441,443,446,448,450,452,454],{"class":182,"line":442},19,[180,444,445],{"class":279},"        status",[180,447,324],{"class":197},[180,449,211],{"class":197},[180,451,414],{"class":214},[180,453,283],{"class":197},[180,455,334],{"class":197},[180,457,459,462,464,466,469,471],{"class":182,"line":458},20,[180,460,461],{"class":279},"        error",[180,463,324],{"class":197},[180,465,211],{"class":197},[180,467,468],{"class":214},"Database connection failed",[180,470,283],{"class":197},[180,472,334],{"class":197},[180,474,476],{"class":182,"line":475},21,[180,477,478],{"class":197},"      },\n",[180,480,482,485,488,490,494],{"class":182,"line":481},22,[180,483,484],{"class":197},"      {",[180,486,487],{"class":279}," status",[180,489,324],{"class":197},[180,491,493],{"class":492},"sbssI"," 503",[180,495,496],{"class":197}," }\n",[180,498,500],{"class":182,"line":499},23,[180,501,502],{"class":279},"    )\n",[180,504,506],{"class":182,"line":505},24,[180,507,508],{"class":197},"  }\n",[180,510,512],{"class":182,"line":511},25,[180,513,514],{"class":197},"}\n",[12,516,517],{},"Monitor this endpoint, not the homepage. The homepage can return 200 even when your database is completely unreachable - it might just serve cached static content while your users get errors on every page that requires data.",[159,519,521],{"id":520},"_2-your-most-critical-user-facing-api-routes","2. Your most critical user-facing API routes",[12,523,524],{},"For a SaaS app, this typically means:",[526,527,528,536,539],"ul",{},[529,530,531,532,535],"li",{},"Authentication endpoint (",[150,533,534],{},"\u002Fapi\u002Fauth\u002Fsession"," or similar)",[529,537,538],{},"Your most-used data fetch endpoint",[529,540,541],{},"Any payment-critical routes",[12,543,544,545,548,549,552],{},"A 500 on ",[150,546,547],{},"\u002Fapi\u002Fauth"," means nobody can log in. A 500 on ",[150,550,551],{},"\u002Fapi\u002Fcheckout"," means you're losing revenue. Your homepage might still be perfectly green.",[159,554,556],{"id":555},"_3-critical-serverless-functions","3. Critical serverless functions",[12,558,559],{},"If you use Vercel serverless functions for background processing, webhooks, or data pipelines, monitor those endpoints directly. A function crash won't affect the frontend but can silently break your entire data layer.",[159,561,563],{"id":562},"_4-edge-middleware-if-you-use-it","4. Edge middleware, if you use it",[12,565,566],{},"If you have Vercel Edge Middleware (for auth, redirects, A\u002FB testing, or geolocation), it runs before your pages and API routes. A middleware error can take down the entire application silently. Add a test path that goes through middleware:",[171,568,570],{"className":173,"code":569,"language":175,"meta":176,"style":176},"\u002F\u002F middleware.ts\nexport function middleware(request: NextRequest) {\n  \u002F\u002F If this path is \u002Fapi\u002Fhealth, skip middleware\n  if (request.nextUrl.pathname === '\u002Fapi\u002Fhealth') {\n    return NextResponse.next()\n  }\n  \u002F\u002F ... your actual middleware logic\n}\n",[150,571,572,577,603,608,640,655,659,664],{"__ignoreMap":176},[180,573,574],{"class":182,"line":183},[180,575,576],{"class":186},"\u002F\u002F middleware.ts\n",[180,578,579,581,583,586,588,592,594,598,601],{"class":182,"line":190},[180,580,231],{"class":193},[180,582,238],{"class":234},[180,584,585],{"class":241}," middleware",[180,587,280],{"class":197},[180,589,591],{"class":590},"sHdIc","request",[180,593,324],{"class":197},[180,595,597],{"class":596},"sBMFI"," NextRequest",[180,599,600],{"class":197},")",[180,602,248],{"class":197},[180,604,605],{"class":182,"line":221},[180,606,607],{"class":186},"  \u002F\u002F If this path is \u002Fapi\u002Fhealth, skip middleware\n",[180,609,610,613,615,617,619,622,624,627,630,632,634,636,638],{"class":182,"line":228},[180,611,612],{"class":193},"  if",[180,614,411],{"class":279},[180,616,591],{"class":201},[180,618,273],{"class":197},[180,620,621],{"class":201},"nextUrl",[180,623,273],{"class":197},[180,625,626],{"class":201},"pathname",[180,628,629],{"class":197}," ===",[180,631,211],{"class":197},[180,633,168],{"class":214},[180,635,283],{"class":197},[180,637,417],{"class":279},[180,639,315],{"class":197},[180,641,642,644,647,649,652],{"class":182,"line":251},[180,643,302],{"class":193},[180,645,646],{"class":201}," NextResponse",[180,648,273],{"class":197},[180,650,651],{"class":241},"next",[180,653,654],{"class":279},"()\n",[180,656,657],{"class":182,"line":259},[180,658,508],{"class":197},[180,660,661],{"class":182,"line":265},[180,662,663],{"class":186},"  \u002F\u002F ... your actual middleware logic\n",[180,665,666],{"class":182,"line":294},[180,667,514],{"class":197},[12,669,670],{},"Then monitor a path that does exercise middleware (like a protected route that should redirect) and confirm the expected response code.",[672,673],"hr",{},[25,675,677],{"id":676},"setting-up-monitoring-for-vercel-with-vantaj","Setting Up Monitoring for Vercel with Vantaj",[159,679,681],{"id":680},"step-1-create-your-health-check-endpoint","Step 1: Create your health check endpoint",[12,683,684,685,687],{},"Add the ",[150,686,168],{}," route from above to your Next.js project.",[159,689,691],{"id":690},"step-2-add-monitors","Step 2: Add monitors",[12,693,694],{},"In Vantaj, add the following monitors:",[171,696,701],{"className":697,"code":699,"language":700},[698],"language-text","Monitor 1: Health Check\nURL: https:\u002F\u002Fyourapp.com\u002Fapi\u002Fhealth\nType: HTTP\nExpected status: 200\nInterval: 1 minute\n\nMonitor 2: Authentication\nURL: https:\u002F\u002Fyourapp.com\u002Fapi\u002Fauth\u002Fsession\nType: HTTP\nExpected status: 200 or 401 (both mean the route is working)\nInterval: 1 minute\n\nMonitor 3: Homepage (static)\nURL: https:\u002F\u002Fyourapp.com\nType: HTTP\nExpected status: 200\nInterval: 5 minutes\n\nMonitor 4: SSL Certificate\nURL: https:\u002F\u002Fyourapp.com\nType: SSL\nAlert: 30 days before expiry\n","text",[150,702,699],{"__ignoreMap":176},[159,704,706],{"id":705},"step-3-configure-multi-region-checks","Step 3: Configure multi-region checks",[12,708,709],{},"Vercel serves traffic from edge locations globally. Set up your monitoring to check from multiple regions to distinguish between:",[526,711,712,718],{},[529,713,714,717],{},[60,715,716],{},"Global outage",": All regions see failure → your app is actually down",[529,719,720,723],{},[60,721,722],{},"Vercel edge node issue",": One region sees failure, others pass → regional CDN issue",[12,725,726],{},"With Vantaj's multi-region consensus, this happens automatically - an alert only fires when multiple independent probe locations confirm the failure. This prevents false positives from transient Vercel edge node issues.",[159,728,730],{"id":729},"step-4-set-up-status-page","Step 4: Set up status page",[12,732,733],{},"Optionally, create a public status page showing the health of your application. Link it from your app's footer and help documentation so customers know where to check during outages.",[672,735],{},[25,737,739],{"id":738},"common-mistakes-when-monitoring-vercel-apps","Common Mistakes When Monitoring Vercel Apps",[159,741,743],{"id":742},"monitoring-only-the-homepage","Monitoring only the homepage",[12,745,746],{},"The most common mistake. A static homepage served from Vercel's CDN can return 200 while every serverless function in your app is crashing. Always include at least one API route that exercises your database or critical backend logic.",[159,748,750,751,754],{"id":749},"monitoring-the-vercelapp-preview-url-instead-of-production","Monitoring the ",[150,752,753],{},"vercel.app"," preview URL instead of production",[12,756,757],{},"Preview deployments have different URLs. Monitor your production domain, not the default Vercel URL.",[159,759,761],{"id":760},"not-handling-cold-starts-in-alerting","Not handling cold starts in alerting",[12,763,764],{},"Vercel serverless functions have cold starts - the first request after a period of inactivity can take 1–3 seconds longer than warm requests. Some monitoring tools treat cold start latency spikes as outages.",[12,766,767],{},"The fix: use a timeout threshold that accounts for cold starts (3–5 seconds rather than the default 1–2 seconds), and rely on HTTP status codes (500\u002F503) rather than latency alone to determine \"down\" vs \"slow.\"",[159,769,771],{"id":770},"missing-the-vercel-platform-status","Missing the Vercel Platform status",[12,773,774,775,782],{},"Monitor your own app, but also know when Vercel itself has issues. Subscribe to ",[776,777,781],"a",{"href":778,"rel":779},"https:\u002F\u002Fvercel-status.com",[780],"nofollow","Vercel's status page"," updates. When Vercel has a platform incident, every app deployed there is affected - including yours. Your monitoring will detect it through your endpoint, but having Vercel's status page in your feed helps you quickly distinguish \"my code is broken\" from \"Vercel is having issues.\"",[159,784,786],{"id":785},"no-ssl-monitoring","No SSL monitoring",[12,788,789],{},"Vercel handles SSL certificate provisioning automatically, but auto-renewal can fail. Monitor your SSL certificate expiry and set up alerts for 30+ days before expiry. A failed renewal is rare but catastrophic - your entire site goes red in browsers with no warning.",[672,791],{},[25,793,795],{"id":794},"vercel-specific-configuration-tips","Vercel-Specific Configuration Tips",[159,797,799],{"id":798},"caching-behavior-and-health-checks","Caching behavior and health checks",[12,801,802],{},"Vercel caches aggressively. Make sure your health check endpoint is not cached:",[171,804,806],{"className":173,"code":805,"language":175,"meta":176,"style":176},"\u002F\u002F app\u002Fapi\u002Fhealth\u002Froute.ts\nexport const dynamic = 'force-dynamic' \u002F\u002F Prevent caching\nexport const revalidate = 0\n\nexport async function GET() {\n  \u002F\u002F ... health check logic\n}\n",[150,807,808,812,835,849,853,867,872],{"__ignoreMap":176},[180,809,810],{"class":182,"line":183},[180,811,187],{"class":186},[180,813,814,816,819,822,825,827,830,832],{"class":182,"line":190},[180,815,231],{"class":193},[180,817,818],{"class":234}," const",[180,820,821],{"class":201}," dynamic ",[180,823,824],{"class":197},"=",[180,826,211],{"class":197},[180,828,829],{"class":214},"force-dynamic",[180,831,283],{"class":197},[180,833,834],{"class":186}," \u002F\u002F Prevent caching\n",[180,836,837,839,841,844,846],{"class":182,"line":221},[180,838,231],{"class":193},[180,840,818],{"class":234},[180,842,843],{"class":201}," revalidate ",[180,845,824],{"class":197},[180,847,848],{"class":492}," 0\n",[180,850,851],{"class":182,"line":228},[180,852,225],{"emptyLinePlaceholder":224},[180,854,855,857,859,861,863,865],{"class":182,"line":251},[180,856,231],{"class":193},[180,858,235],{"class":234},[180,860,238],{"class":234},[180,862,242],{"class":241},[180,864,245],{"class":197},[180,866,248],{"class":197},[180,868,869],{"class":182,"line":259},[180,870,871],{"class":186},"  \u002F\u002F ... health check logic\n",[180,873,874],{"class":182,"line":265},[180,875,514],{"class":197},[12,877,878],{},"If your health endpoint is cached, monitoring will always return 200 even during an outage.",[159,880,882],{"id":881},"serverless-function-timeouts","Serverless function timeouts",[12,884,885],{},"Vercel has a default serverless function timeout of 10 seconds (configurable to 30s on Pro, 900s on Enterprise). If your health check depends on a slow database query, it might time out under load and return a 504 to your monitoring. Set your monitoring timeout to 8–9 seconds for health endpoints to catch these before Vercel's own timeout kicks in.",[159,887,889],{"id":888},"environment-variables-and-deployment-failures","Environment variables and deployment failures",[12,891,892,893,895],{},"If a deployment fails to load environment variables correctly, your serverless functions will crash on startup. A health check that tests database connectivity (",[150,894,286],{},") will immediately surface this - the function will return 500 or crash with a missing environment variable error.",[12,897,898],{},"This is one of the most common causes of \"site went down after a deploy\" incidents on Vercel.",[672,900],{},[25,902,904],{"id":903},"monitoring-nextjs-app-router-vs-pages-router","Monitoring Next.js App Router vs Pages Router",[12,906,907],{},"Both work fine with standard HTTP monitoring, but there are differences in how you write health checks:",[12,909,910,411,913,916],{},[60,911,912],{},"Pages Router",[150,914,915],{},"pages\u002Fapi\u002Fhealth.ts","):",[171,918,920],{"className":173,"code":919,"language":175,"meta":176,"style":176},"import type { NextApiRequest, NextApiResponse } from 'next'\n\nexport default async function handler(req: NextApiRequest, res: NextApiResponse) {\n  res.setHeader('Cache-Control', 'no-store')\n\n  try {\n    \u002F\u002F test your database\n    res.status(200).json({ status: 'ok' })\n  } catch (e) {\n    res.status(503).json({ status: 'error' })\n  }\n}\n",[150,921,922,950,954,990,1020,1024,1030,1035,1075,1090,1127,1131],{"__ignoreMap":176},[180,923,924,926,929,931,934,937,940,942,944,946,948],{"class":182,"line":183},[180,925,194],{"class":193},[180,927,928],{"class":193}," type",[180,930,198],{"class":197},[180,932,933],{"class":201}," NextApiRequest",[180,935,936],{"class":197},",",[180,938,939],{"class":201}," NextApiResponse",[180,941,205],{"class":197},[180,943,208],{"class":193},[180,945,211],{"class":197},[180,947,651],{"class":214},[180,949,218],{"class":197},[180,951,952],{"class":182,"line":190},[180,953,225],{"emptyLinePlaceholder":224},[180,955,956,958,961,963,965,968,970,973,975,977,979,982,984,986,988],{"class":182,"line":221},[180,957,231],{"class":193},[180,959,960],{"class":193}," default",[180,962,235],{"class":234},[180,964,238],{"class":234},[180,966,967],{"class":241}," handler",[180,969,280],{"class":197},[180,971,972],{"class":590},"req",[180,974,324],{"class":197},[180,976,933],{"class":596},[180,978,936],{"class":197},[180,980,981],{"class":590}," res",[180,983,324],{"class":197},[180,985,939],{"class":596},[180,987,600],{"class":197},[180,989,248],{"class":197},[180,991,992,995,997,1000,1002,1004,1007,1009,1011,1013,1016,1018],{"class":182,"line":228},[180,993,994],{"class":201},"  res",[180,996,273],{"class":197},[180,998,999],{"class":241},"setHeader",[180,1001,280],{"class":279},[180,1003,283],{"class":197},[180,1005,1006],{"class":214},"Cache-Control",[180,1008,283],{"class":197},[180,1010,936],{"class":197},[180,1012,211],{"class":197},[180,1014,1015],{"class":214},"no-store",[180,1017,283],{"class":197},[180,1019,291],{"class":279},[180,1021,1022],{"class":182,"line":251},[180,1023,225],{"emptyLinePlaceholder":224},[180,1025,1026,1028],{"class":182,"line":259},[180,1027,254],{"class":193},[180,1029,248],{"class":197},[180,1031,1032],{"class":182,"line":265},[180,1033,1034],{"class":186},"    \u002F\u002F test your database\n",[180,1036,1037,1040,1042,1045,1047,1050,1052,1054,1056,1058,1061,1063,1065,1067,1069,1071,1073],{"class":182,"line":294},[180,1038,1039],{"class":201},"    res",[180,1041,273],{"class":197},[180,1043,1044],{"class":241},"status",[180,1046,280],{"class":279},[180,1048,1049],{"class":492},"200",[180,1051,600],{"class":279},[180,1053,273],{"class":197},[180,1055,310],{"class":241},[180,1057,280],{"class":279},[180,1059,1060],{"class":197},"{",[180,1062,487],{"class":279},[180,1064,324],{"class":197},[180,1066,211],{"class":197},[180,1068,329],{"class":214},[180,1070,283],{"class":197},[180,1072,205],{"class":197},[180,1074,291],{"class":279},[180,1076,1077,1079,1081,1083,1086,1088],{"class":182,"line":299},[180,1078,405],{"class":197},[180,1080,408],{"class":193},[180,1082,411],{"class":279},[180,1084,1085],{"class":201},"e",[180,1087,417],{"class":279},[180,1089,315],{"class":197},[180,1091,1092,1094,1096,1098,1100,1103,1105,1107,1109,1111,1113,1115,1117,1119,1121,1123,1125],{"class":182,"line":318},[180,1093,1039],{"class":201},[180,1095,273],{"class":197},[180,1097,1044],{"class":241},[180,1099,280],{"class":279},[180,1101,1102],{"class":492},"503",[180,1104,600],{"class":279},[180,1106,273],{"class":197},[180,1108,310],{"class":241},[180,1110,280],{"class":279},[180,1112,1060],{"class":197},[180,1114,487],{"class":279},[180,1116,324],{"class":197},[180,1118,211],{"class":197},[180,1120,414],{"class":214},[180,1122,283],{"class":197},[180,1124,205],{"class":197},[180,1126,291],{"class":279},[180,1128,1129],{"class":182,"line":337},[180,1130,508],{"class":197},[180,1132,1133],{"class":182,"line":362},[180,1134,514],{"class":197},[12,1136,1137,411,1140,916],{},[60,1138,1139],{},"App Router",[150,1141,1142],{},"app\u002Fapi\u002Fhealth\u002Froute.ts",[171,1144,1146],{"className":173,"code":1145,"language":175,"meta":176,"style":176},"export const dynamic = 'force-dynamic'\n\nexport async function GET() {\n  try {\n    \u002F\u002F test your database\n    return Response.json({ status: 'ok' })\n  } catch (e) {\n    return Response.json({ status: 'error' }, { status: 503 })\n  }\n}\n",[150,1147,1148,1164,1168,1182,1188,1192,1220,1234,1273,1277],{"__ignoreMap":176},[180,1149,1150,1152,1154,1156,1158,1160,1162],{"class":182,"line":183},[180,1151,231],{"class":193},[180,1153,818],{"class":234},[180,1155,821],{"class":201},[180,1157,824],{"class":197},[180,1159,211],{"class":197},[180,1161,829],{"class":214},[180,1163,218],{"class":197},[180,1165,1166],{"class":182,"line":190},[180,1167,225],{"emptyLinePlaceholder":224},[180,1169,1170,1172,1174,1176,1178,1180],{"class":182,"line":221},[180,1171,231],{"class":193},[180,1173,235],{"class":234},[180,1175,238],{"class":234},[180,1177,242],{"class":241},[180,1179,245],{"class":197},[180,1181,248],{"class":197},[180,1183,1184,1186],{"class":182,"line":228},[180,1185,254],{"class":193},[180,1187,248],{"class":197},[180,1189,1190],{"class":182,"line":251},[180,1191,1034],{"class":186},[180,1193,1194,1196,1198,1200,1202,1204,1206,1208,1210,1212,1214,1216,1218],{"class":182,"line":259},[180,1195,302],{"class":193},[180,1197,305],{"class":201},[180,1199,273],{"class":197},[180,1201,310],{"class":241},[180,1203,280],{"class":279},[180,1205,1060],{"class":197},[180,1207,487],{"class":279},[180,1209,324],{"class":197},[180,1211,211],{"class":197},[180,1213,329],{"class":214},[180,1215,283],{"class":197},[180,1217,205],{"class":197},[180,1219,291],{"class":279},[180,1221,1222,1224,1226,1228,1230,1232],{"class":182,"line":265},[180,1223,405],{"class":197},[180,1225,408],{"class":193},[180,1227,411],{"class":279},[180,1229,1085],{"class":201},[180,1231,417],{"class":279},[180,1233,315],{"class":197},[180,1235,1236,1238,1240,1242,1244,1246,1248,1250,1252,1254,1256,1258,1261,1263,1265,1267,1269,1271],{"class":182,"line":294},[180,1237,302],{"class":193},[180,1239,305],{"class":201},[180,1241,273],{"class":197},[180,1243,310],{"class":241},[180,1245,280],{"class":279},[180,1247,1060],{"class":197},[180,1249,487],{"class":279},[180,1251,324],{"class":197},[180,1253,211],{"class":197},[180,1255,414],{"class":214},[180,1257,283],{"class":197},[180,1259,1260],{"class":197}," },",[180,1262,198],{"class":197},[180,1264,487],{"class":279},[180,1266,324],{"class":197},[180,1268,493],{"class":492},[180,1270,205],{"class":197},[180,1272,291],{"class":279},[180,1274,1275],{"class":182,"line":299},[180,1276,508],{"class":197},[180,1278,1279],{"class":182,"line":318},[180,1280,514],{"class":197},[672,1282],{},[25,1284,1286],{"id":1285},"what-good-vercel-monitoring-looks-like","What Good Vercel Monitoring Looks Like",[12,1288,1289],{},"After setup, you should have:",[33,1291,1292,1305],{},[36,1293,1294],{},[39,1295,1296,1299,1302],{},[42,1297,1298],{},"Monitor",[42,1300,1301],{},"Purpose",[42,1303,1304],{},"Alert on",[52,1306,1307,1319,1331,1342,1353],{},[39,1308,1309,1313,1316],{},[57,1310,1311],{},[150,1312,168],{},[57,1314,1315],{},"Tests database + app layer",[57,1317,1318],{},"Non-200 status or >5s response",[39,1320,1321,1325,1328],{},[57,1322,1323],{},[150,1324,534],{},[57,1326,1327],{},"Tests auth layer",[57,1329,1330],{},"Non-200\u002F401 status",[39,1332,1333,1336,1339],{},[57,1334,1335],{},"Homepage",[57,1337,1338],{},"Tests CDN delivery",[57,1340,1341],{},"Non-200 status",[39,1343,1344,1347,1350],{},[57,1345,1346],{},"SSL certificate",[57,1348,1349],{},"Tests cert validity",[57,1351,1352],{},"30 days before expiry",[39,1354,1355,1358,1361],{},[57,1356,1357],{},"Domain expiry",[57,1359,1360],{},"Tests domain registration",[57,1362,1363],{},"60 days before expiry",[12,1365,1366],{},"With these five monitors, you'll catch:",[526,1368,1369,1372,1375,1378,1381],{},[529,1370,1371],{},"Vercel platform outages",[529,1373,1374],{},"Serverless function crashes",[529,1376,1377],{},"Database connection failures",[529,1379,1380],{},"Authentication layer failures",[529,1382,1383],{},"SSL\u002Fdomain renewal failures",[12,1385,1386],{},"What you won't catch with HTTP monitoring alone:",[526,1388,1389,1392,1395],{},[529,1390,1391],{},"Build failures (monitor your CI\u002FCD logs separately)",[529,1393,1394],{},"Edge cache serving stale content (requires content validation)",[529,1396,1397],{},"Performance regressions (requires APM, not uptime monitoring)",[672,1399],{},[25,1401,1403],{"id":1402},"quick-setup","Quick Setup",[12,1405,1406],{},"If you want to get this running today:",[1408,1409,1410,1416,1419,1428,1431],"ol",{},[529,1411,1412,1413,1415],{},"Add a ",[150,1414,168],{}," endpoint to your Next.js app (code above)",[529,1417,1418],{},"Deploy to Vercel",[529,1420,1421,1422,1427],{},"Start monitoring at ",[776,1423,1426],{"href":1424,"rel":1425},"https:\u002F\u002Fapp.vantaj.co\u002Fregister",[780],"app.vantaj.co"," - free tier includes 20 monitors, multi-region consensus, and SSL monitoring",[529,1429,1430],{},"Add the 4–5 monitors described above",[529,1432,1433],{},"Configure Slack or email alerts",[12,1435,1436],{},"The whole setup takes about 10 minutes and gives you coverage for the failure modes that actually take down Vercel-hosted production apps.",[1438,1439,1440],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}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 .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}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 .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}",{"title":176,"searchDepth":190,"depth":190,"links":1442},[1443,1444,1450,1456,1464,1469,1470,1471],{"id":27,"depth":190,"text":28},{"id":156,"depth":190,"text":157,"children":1445},[1446,1447,1448,1449],{"id":161,"depth":221,"text":162},{"id":520,"depth":221,"text":521},{"id":555,"depth":221,"text":556},{"id":562,"depth":221,"text":563},{"id":676,"depth":190,"text":677,"children":1451},[1452,1453,1454,1455],{"id":680,"depth":221,"text":681},{"id":690,"depth":221,"text":691},{"id":705,"depth":221,"text":706},{"id":729,"depth":221,"text":730},{"id":738,"depth":190,"text":739,"children":1457},[1458,1459,1461,1462,1463],{"id":742,"depth":221,"text":743},{"id":749,"depth":221,"text":1460},"Monitoring the vercel.app preview URL instead of production",{"id":760,"depth":221,"text":761},{"id":770,"depth":221,"text":771},{"id":785,"depth":221,"text":786},{"id":794,"depth":190,"text":795,"children":1465},[1466,1467,1468],{"id":798,"depth":221,"text":799},{"id":881,"depth":221,"text":882},{"id":888,"depth":221,"text":889},{"id":903,"depth":190,"text":904},{"id":1285,"depth":190,"text":1286},{"id":1402,"depth":190,"text":1403},"guides","2026-06-24","Vercel doesn't include uptime monitoring. Here's how to monitor your Vercel deployments, edge functions, and API routes properly - including what to check and what common tools miss.","md",null,{},"\u002Fblog\u002Fuptime-monitoring-vercel",{"title":5,"description":1474},"blog\u002Fuptime-monitoring-vercel","LaW1b6onBQd9wvBEcBWxOieFDPKCM0Il3azyy45T-nE",1782314800217]