Every five minutes
An ordinary request for the production URL, the way a browser would make it, then the certificate and the security headers. The answer is one of three states:
- Healthy. The page answered 2xx over HTTPS, in time. Missing security headers are listed beside the result; they do not change the state.
- Degraded. Something is off but visitors can still use the site: a slow answer, a redirect down to plain HTTP, or a status that is unusual without being an outage. Shown on the screens, never sent to anybody’s inbox.
- Critical. The site could not be reached, answered a 5xx, or answered one of the 4xx statuses below that mean a visitor gets nothing. An incident opens after the failure is seen on two consecutive checks, so a single blip never pages anyone.
What each 4xx means for your visitors
The monitor does not file every 4xx as the same thing. A visitor experiences 404 as the site being gone; nobody experiences 429 that way, because it is the monitor being throttled and not the public. Only the statuses where the honest answer to “does a visitor get a working site” is no open an incident.
| Status | Read as | Opens an incident |
|---|---|---|
| 400 | The server would not accept an ordinary request for the page. | Yes |
| 401 | The page is behind a password prompt. | Yes |
| 402 | The host is refusing to serve the site until something is paid. | Yes |
| 403 | The page is being refused rather than served. | Yes |
| 404 | There is nothing at this address. | Yes |
| 410 | The address is being reported as permanently removed. | Yes |
| 451 | The host or a network in front of it is blocking the page. | Yes |
| 429 | Our monitor is being rate limited, so we cannot see the page. Your visitors may be fine. | No — degraded |
401 and 403 are the two that can be a firewall singling out the monitor while real visitors are fine; the incident says so and tells you how to tell in ten seconds — open the address in a private window. A 4xx not in the table is recorded as unusual and never alerted on.
What each connection adds
The five-minute check is the floor. Each connected provider adds one of these on top:
- Money · Revenue Guard. Payments against a learned baseline, webhook health, checkout evidence. Stripe.
- Publishes · Publish Verification. Every deploy gets a verdict within five minutes. Vercel, Netlify, Cloudflare, Render, Fly.io, Railway.
- Spend · Cost Guard. AI and hosting usage against budgets, spike alerts. OpenAI, Anthropic.
- Backend. Database and auth health, config drift, security advisors, whether auth email can be delivered. Supabase.
- Errors. Runtime errors so incidents say what broke. Sentry, Error capture.
- Code. What changed in each publish, and later, repairs. GitHub.
When a key is found in public code, an OpenRouter management key lets Keelnest see which key it is, what it spent and when it’s off.
Journeys
A journey is the steps a customer takes — sign in, add to basket, reach the pay step — written in the builder’s language and walked in a real browser.
- It runs on the schedule your plan sets, and again after every publish.
- A failed step is retried before anything is said, so a verdict is never one bad run.
- A payment journey stops before the pay step: nothing is ever charged.
- Where the site asks for an email address, a journey may type
{{inbox}}, an address minted for that run. A “Wait for email” step then opens the link the site sends there, so a sign-up, a magic link or a password reset is walked to the end.
Previews
- Every Vercel or Netlify branch or pull-request preview is checked within five minutes of being ready, before anybody promotes it.
- HTTP, SSL and the app’s running journeys, on the preview’s own address. The variable and redirect checks stay with production publishes.
- A failing preview is emailed under the same switch as a broken publish — the same news, told earlier. It never changes the app’s health or opens an incident: it is not the customer’s site.
- A preview the host protects from outside visitors shows as “unopened”, with the setting to change — never as failed.
Config check on pull requests
- Off until you turn it on for an app, under Configuration. It needs the app’s GitHub repository and its host.
- Each pull request into the main branch, and each push to it, is read, usually within five minutes: only the lines the change adds. Pull requests from forks and from Dependabot or Renovate are skipped.
- It flags a variable the new code reads that is set nowhere, a secret in a variable starting with
NEXT_PUBLIC_,VITE_orEXPO_PUBLIC_, and a migration that turns off row-level security or removes a policy without adding one. - Each pull request gets a check named Keelnest on GitHub, with each finding on the line it is about. If the Keelnest GitHub App on your account has not accepted the Checks permission, it comments instead: one comment per pull request, updated as it changes, and only when there is something to fix. On a public repository the check and the comment give the count and a link to Keelnest. Pushes straight to the main branch are shown in Keelnest only.
- Advisory by default: the check never fails, and problems show as Neutral. When the host builds a preview of the pull request (Vercel, Netlify, or a Cloudflare Worker that builds with Workers Builds), the preview’s check and journeys are added. It reads variable names, never their values, and uses no AI credits.
Blocking a merge
- On Studio and above, an owner can turn on Block merging when the check fails, under the app’s Configuration. The Keelnest check then fails when something would break or leak, or when the preview fails. While it is on, only the owner can turn the config check off, stop watching the app or change its repository, and changing the repository turns blocking off. On other plans the check stays advisory.
- GitHub stops the merge only when the check is required. On GitHub open the repository’s Settings › Rules › Rulesets › New branch ruleset, target the default branch, set it Active, tick Require status checks to pass, add Keelnest and choose Keelnest as its source. Classic branch protection under Settings › Branches works too. Then press Check again on the card, and open pull requests are checked too.
- Keelnest appears in GitHub’s list after it has checked a pull request in the last 7 days. Requiring a check on a private repository needs a paid GitHub plan (Pro, Team or Enterprise). Merge queues are not supported yet.
- Pull requests from forks, Dependabot or Renovate updates the bot pushed itself as its own signed commits, and every pull request while Keelnest watches none of the repository’s apps (paused, or its client offboarded) get a skipped check; blocking does not cover them. A check Keelnest could not finish is Neutral. Re-run on the Keelnest check reads the change again, and checks a failed preview again while the host still lists it. Before you turn the config check off, archive the app or remove the GitHub App, remove Keelnest from the required checks.
Once a day
Where the app’s name resolves, how long its certificate has, and when its domain registration runs out, read from the domain’s own registry (RDAP). An incident opens at fourteen days left for either. An app on a builder’s or host’s own address, like name.lovable.app, has no registration of its own to renew. Some registries, including .io, .co and .de, do not publish the renewal date this way, so those domains are not covered yet.
Check again
Every open incident has a Check again button.
- It runs the check that opened the incident, for that app, now: the site probe, the Supabase reads, a publish’s verification, the failing journeys or the Stripe reconciliation.
- It is one more reading under the same rules. An incident resolves when its rule is satisfied — usually two good readings in a row.
- Right after you change a setting, you learn whether it took instead of waiting for the next check.
- Beside it, the incident links to the provider page where the fix is made.
What is kept, and for how long
- Observation data is kept for a fixed window per kind — payments, AI usage and daily spend for 62 days, HTTP, SSL and header checks for 62 days, journey runs for 62 days, error events for 15 days — then deleted.
- The window is the same on every tier, and a daily check confirms the database is obeying it.
- Failure screenshots are kept for 30 days. One attached to an incident is evidence: it is kept for as long as that incident is open, and for 30 days after it closes.
- After each publish Keelnest reads your key public pages in a browser and keeps one sanitized screenshot of each. A reading is kept for 30 days after a newer reading of the same page replaces it; the newest one of each key page is kept, because the next publish is compared with it.
- The workspace activity feed is kept for 365 days.