What synthetic API monitoring actually does for a small team

If you ship an API product and your traffic is still thin, the worst failures are the ones nobody reports. A paying customer runs a request at 4 a.m. and gets a 500. By the time they email support, your reputation has already taken the hit. Synthetic API monitoring is the practice of writing a script that pretends to be a user, hits your own endpoints on a schedule, and yells at you when something is wrong.

For an indie team, the whole idea is small but powerful: simulate the requests a real customer would make, assert what a correct response looks like, and page someone the moment the assertion fails. That is the difference between synthetic monitoring and a plain uptime check. An uptime check tells you the server answered. A synthetic check tells you the server answered the right thing.

This guide is built around the founder’s lens: how do you spend less time firefighting, deliver work you can stand behind, and avoid paying enterprise prices for a problem that fits on one screen. No invented benchmarks, no vendor pitches, just the trade-offs you actually face.

Synthetic monitoring vs. a plain uptime check

The cheapest thing you can wire up is an HTTP HEAD request to your health endpoint, every minute, from a cron job. That will catch a totally dead server. It will not catch much else.

Synthetic monitoring adds two layers on top:

  • Request path fidelity. Instead of hitting /health, you replay the actual flow a customer uses — POST /login, then GET /account, then POST /charge. You are testing the business logic, not the kernel.
  • Assertions on the response. Status code is the floor. You also check that the JSON has the keys you expect, that a numeric field is in range, that a token round-trips, or that a specific error string is absent.

If your product is a thin proxy over a third-party API, the synthetic check is often the only place where you find out the upstream changed its schema. That is a real category of bug a HEAD ping will never see.

The trade-off is cost and complexity. Plain uptime checks are free at most providers and nearly free to self-host. Synthetic checks cost more because each run is heavier, and they need maintenance every time you change an endpoint.

What request paths and assertions actually catch

For a small team, the highest-value checks are the ones that map to revenue. A useful mental list, in roughly descending value:

  1. The auth round-trip. Sign up, log in, get a token, call a protected endpoint. Catches broken OAuth flows, expired JWT secrets, CORS regressions, and rate limiter misconfigurations.
  2. The core write path. For a billing API, that is POST /charge. For a CRM, POST /contact. Assert that the response body contains an id, that the database row appears, and that the latency is within budget.
  3. The third-party dependency probe. If your API depends on Stripe, OpenAI, or an LLM provider, hit a cheap endpoint on that provider as part of the same script. You find out about upstream outages before your customers blame you.
  4. The error-shape guard. Deliberately send a bad request and assert the error response matches your documented schema. Catches silent 200s with empty bodies, which are the worst kind of bug because they look fine in logs.
  5. The latency floor. Not just “is it up” but “is p95 under 800 ms from a real region.” Latency regressions often ship before functional regressions because nobody notices in dev.

The pattern that saves the most time is the two-step check: one happy-path assertion that proves the feature works, and one negative-path assertion that proves the failure mode is handled. Anything beyond that is usually diminishing returns for a team of one to three.

Where synthetic checks beat a local cron job

A local cron job on your laptop is the cheapest possible monitor and the worst possible monitor. It catches nothing when the laptop is asleep, in airplane mode, or behind your home firewall. It does not represent the experience of a customer in Frankfurt hitting your endpoint in us-east-1.

Hosted runners fix three specific problems:

  • Geography. Your real customers are rarely in the same region as your server. A synthetic check from a runner in eu-west-2 tells you about transatlantic latency and EU-only regulatory failures that a cron in Iowa cannot.
  • Persistence. Hosted runners run whether or not your laptop is closed. That sounds obvious. It is the single most common reason indie teams miss 3 a.m. incidents.
  • Independence from your stack. A cron job running on the same server you are testing cannot distinguish “my server is broken” from “my monitoring is broken.” Hosted runners are deliberately outside your blast radius.

Hosted runners cost money, though. The common shape of the trade-off:

  • A free tier covers a handful of checks every few minutes.
  • Paid tiers charge per check frequency, per region, or per check count.
  • Browser-based checks (full Playwright runs through a UI) are typically priced separately from API checks and can run 5–10x the cost.

For an indie team, the right move is almost always: API checks on a hosted runner, browser checks only for the one or two flows that actually move revenue, and a local cron as a redundant last-resort alarm wired to a different channel than your main monitor.

How to keep synthetic checks cheap at low traffic

The two levers that matter are frequency and assertion depth. Each is roughly independent.

Frequency. Every minute is paranoid. Every fifteen minutes is the usual default for paid tiers. Every hour is plenty for a non-customer-facing internal API. The right answer depends on your mean time to detect budget — how long can something be broken before you would lose money? If a 30-minute outage costs you one support ticket, every 15 minutes is fine. If a 5-minute outage costs you an SLA breach with a paying enterprise customer, you need every minute and you need a hosted runner in their region.

Assertion depth. A status code check is nearly free. A JSON body parse is cheap. A full database query inside the assertion is expensive and usually wrong — if your check script can read the production database directly, you have coupled your monitor to your data layer, which means your monitor will break in the same ways your service breaks. Keep assertions on the response wire, not inside your system.

A simple cost-control rule of thumb: each check should cost less than what one minute of downtime costs you. If a check is $0.001 per run and you run it every five minutes, that is roughly $9 a month per endpoint. Three endpoints, one region, every fifteen minutes, lands many indie teams in the $20–$50 a month range, which is usually the right spend.

Cheap API monitoring with Playwright (and when not to use it)

Playwright is the default tool a lot of indie developers reach for, because it is already in their stack for E2E tests. That is a reasonable starting point, with two caveats.

First, Playwright is a browser engine. For an API check you do not need a browser. Using Playwright for API-only checks is like using a freight truck to carry a lunchbox. A plain fetch in Node, a curl in a shell script, or a 20-line Python script using httpx will do the same job for a fraction of the compute and the bill. Reserve Playwright for the rare check that needs to exercise a JS-rendered page or a session cookie across redirects.

Second, hosting Playwright on your own box looks free until you count the electricity, the uptime, and the time you spend debugging why the browser process crashed. Most teams that start with self-hosted Playwright runners move to a hosted runner within six months — usually because the false-positive rate from headless browser crashes is higher than the real-incident rate. A hosted runner that speaks the Playwright API directly is usually worth the price.

Synthetic checks versus basic uptime pings: a decision frame

Use this short checklist before you add another monitor.

  • Plain uptime ping is enough when the endpoint is a public health route, the failure mode is total outage, and you do not care about correctness as long as a response came back.
  • Synthetic check is worth it when the failure mode is subtle: a 200 with a wrong body, a slow but successful response, a third-party dependency that quietly returns errors, or an auth flow that broke during a deploy.
  • Real user monitoring (RUM) is worth it when you have real traffic and you want to know how actual customers experience the product. At low traffic, RUM is mostly noise.

For an indie founder, the rule of thumb is: stay on uptime pings until the first time a ping was green and a customer still complained. That is the signal to move up to synthetic checks. Before that signal, synthetic checks are infrastructure you do not yet need.

A simple starter setup you can ship this week

  1. Pick the three endpoints that, if broken, would lose you money today. Usually login, charge, and one read endpoint your dashboard depends on.
  2. Write a script per endpoint that does the happy path and asserts one specific thing — a status code plus one body key, or one latency threshold.
  3. Run the scripts from a hosted runner on a 5–15 minute interval. One region is enough until you have customers in two continents.
  4. Wire the failure alert to a channel you actually look at — email is fine, a chat webhook is better, a phone call is overkill at this stage.
  5. Add a local cron on a cheap VPS as a redundant alarm that points at a different channel. This catches the rare case where your main monitor’s provider has an outage.
  6. Review the false-positive rate after two weeks. If you are waking up more than once a week for non-incidents, loosen the assertions or the frequency. A monitor you ignore is worse than no monitor.

That setup costs roughly the price of one or two cups of coffee a month, runs without you thinking about it, and catches the failure modes that actually matter when you are small.

When synthetic monitoring adds value beyond uptime pings

Synthetic checks earn their keep in three situations that hit small teams disproportionately:

  • Schema drift in third-party APIs. Your code is fine. Their response shape changed. Only an assertion on the body catches this.
  • Slow regressions after a deploy. A new release ships, latency doubles, but no request fails. Uptime pings will report green all day.
  • Geo-distributed bugs. A TLS certificate expires only for visitors from a specific region, or a CDN POP is misconfigured. Only a runner in that region sees it.

If none of these has ever happened to you, you can defer synthetic monitoring and stay with a plain uptime ping. The moment one of them does happen, the cost of the incident usually justifies a year of monitoring spend.

FAQ

How often should a small team run synthetic API checks? Every five to fifteen minutes is a sensible default. Run more often only if a short outage costs you a contractual penalty or a clear chunk of revenue. Running every minute rarely pays for itself at low traffic.

Do I need a browser like Playwright for API checks? Usually no. A plain HTTP client is enough for most assertions. Browser engines add cost, flakiness, and a separate failure surface. Reach for Playwright only when the check must execute JavaScript or follow a session cookie across a real UI.

Can I just use a cron job on my server? You can, but you should not rely on it alone. A cron on the same machine you are testing cannot tell its own failure from your service’s failure, and a cron on your laptop is offline whenever you are. A hosted runner, even a cheap one, removes that blindness.

What is the cheapest way to start? Pick one revenue-critical endpoint, write a 20-line script that hits it and asserts a body key, run it from a free-tier hosted monitor on a fifteen-minute interval, and wire the failure to email. That is a complete starter setup for most indie products.

When should I upgrade to a paid monitor? When you need more than one region, more frequent checks, browser-based flows, or retention of historical results beyond a few days. The upgrade usually pays for itself the first time you catch a regional outage before a customer does.

Sources