Under $5 a month for SaaS monitoring: what's realistic

A worked budget for errors, logs and a couple of charts at a $5/month ceiling — what metered capture buys, what it can't, and when Sentry's free tier wins outright.

At the $5/month ceiling you can have real error capture at small-app volume, unlimited reads of everything you captured, and any chart you’re willing to render yourself. What you can’t have is a hosted dashboard product, alert-rule builders, on-call routing or long retention guarantees. Infrai sits on the first side of that line: errors are metered per captured event and all eight read routes in the namespace are free, so the shape of the bill is “writes only” — and GET /v1/account/usage tells you at any moment what the month has actually cost.

That distinction is the whole answer to the budget question. Tools that bill per seat or per host have a floor you can’t get under — one Datadog host already costs several times $5 — while tools that bill per event let a genuinely small app be genuinely cheap. A side project throwing 3,000 errors a month and a 200-customer SaaS throwing 30,000 are different bills on the second model and identical bills on the first.

The line items

Line itemHow it’s chargedAt 10,000 events/month
Error capture (POST /v1/errors/capture)per captured event, $0.00005$0.50
Group/event reads, search, resolvefree, rate-limited$0.00
Charts built from those readsyour own code$0.00
New-account credit$2 free, ~39,999 captures−$2.00 first month

Verified 2026-07-26. Don’t take the figure on trust — the rate is published on the discovery endpoint and you can read it in one call:

export INFRAI_API_KEY="your_infrai_api_key"

curl -sS "https://api.infrai.cc/v1/discovery" \
  -H "Authorization: Bearer ${INFRAI_API_KEY}" \
  | jq '.capabilities[] | select(.id=="errors.capture") | {id, billing}'

Prices on this platform move downward over time and discount campaigns run, so the number you get back may well be smaller than the one in the table. The durable facts are structural: writes metered, reads free, no seat charge, no host charge, no minimum.

Checking the budget against a real account

Guessing your event volume is the biggest source of error in a budget like this, so measure it. Both of these routes are free.

curl -sS "https://api.infrai.cc/v1/account/balance" \
  -H "Authorization: Bearer ${INFRAI_API_KEY}"
{
  "ok": true,
  "data": {
    "balance_usd": 87.15131448,
    "runway_days": 335.55,
    "daily_avg_spend": 0.25972547,
    "tier": "standard",
    "currency": "USD"
  }
}

runway_days and daily_avg_spend are the two numbers a $5 budget lives or dies on — if daily average spend is above about $0.16, you’re over the ceiling for the month. GET /v1/account/usage breaks the same period down per capability, which tells you whether errors or something else ate the wallet.

One write, then everything else for free

A capture is a single POST. This is the entire integration; there’s no agent, no sidecar and no build step.

curl -sS -X POST "https://api.infrai.cc/v1/errors/capture" \
  -H "Authorization: Bearer ${INFRAI_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "SqliteError: database is locked\n    at withTransaction (/app/src/db.js:19:11)",
    "exception": "SqliteError",
    "fingerprint": "db:withTransaction:SqliteError",
    "environment": "production",
    "release": "1.4.2"
  }'
{
  "ok": true,
  "data": {
    "event_id": "evt_err_k0CVr2V704HZIN0pfMiGiAY7",
    "fingerprint": "cbd63697b8bf4b29555dc7ab90877d24eac24e2838b473e51a227f519666f639",
    "error_group_id": "errgrp_aUhITfSJamDjxCi7FTZF8WJE",
    "is_new_group": true,
    "dashboard_url": "https://infrai.cc/projects/proj_local/errors/evt_err_k0CVr2V704HZIN0pfMiGiAY7"
  }
}

Every subsequent operation on that data — listing groups, pulling the event stream for one group, searching text, marking a group resolved — is free and rate-limited rather than metered. That’s what makes the “couple of basic charts” part of the question affordable: the charts read, and reads don’t bill.

The charts, rendered by 40 lines of Node

curl -sS "https://api.infrai.cc/v1/errors/groups?limit=3" \
  -H "Authorization: Bearer ${INFRAI_API_KEY}"
{
  "ok": true,
  "data": {
    "groups": [
      { "error_group_id": "errgrp_17E05u607XMVSasuMpsrMX7w", "title": "voiceops worker loop error", "count": 19, "level": "error", "is_resolved": false },
      { "error_group_id": "errgrp_xBaxKvlNOuc3s0fAxXSgg2R2", "title": "TimeoutError: payments.charge timed out after 8000ms", "count": 4, "level": "error", "is_resolved": false },
      { "error_group_id": "errgrp_DCZn637btNBwADmDraeaDVCw", "title": "checkout: discount lookup returned null for an active promo", "count": 3, "level": "warning", "is_resolved": false }
    ],
    "next_cursor": "3",
    "total": 60
  }
}

Two charts cover most of what a small team looks at daily: a top-offenders bar chart and a “new since yesterday” list. Both come from that one response.

// chart.mjs — Node 22 ESM. Top error groups as a terminal bar chart, $0 to run.
const KEY = process.env.INFRAI_API_KEY;
if (!KEY) { console.error("set INFRAI_API_KEY"); process.exit(1); }

const res = await fetch("https://api.infrai.cc/v1/errors/groups?limit=20", {
  headers: { authorization: `Bearer ${KEY}` },
});
if (!res.ok) { console.error("groups read failed", res.status, await res.text()); process.exit(1); }

const { data } = await res.json();
const open = data.groups.filter((g) => !g.is_resolved);
const max = Math.max(1, ...open.map((g) => g.count));
const dayAgo = Date.now() - 24 * 60 * 60 * 1000;

console.log(`open groups: ${open.length} of ${data.total}\n`);
for (const g of open.slice(0, 10)) {
  const bar = "█".repeat(Math.max(1, Math.round((g.count / max) * 40)));
  const fresh = Date.parse(g.first_seen_at) > dayAgo ? " ← new today" : "";
  console.log(`${String(g.count).padStart(5)} ${bar} ${g.title.split("\n")[0].slice(0, 48)}${fresh}`);
}

Point that at a cron job every morning and you have a daily digest. The same key can send it — email and cron are namespaces on the same account, which is the practical reason a one-credential platform beats four free tiers glued together at this budget.

What $5 doesn’t buy

Be clear-eyed about the gaps, because they’re real.

There’s no support for source maps and no frame-level stack traces: whatever you send as exception is stored as {"type": "Message", "value": "…", "stacktrace": []}, so the stack lives in your message text or nowhere. There’s no alert-rule UI, so “email me when this group crosses 50 events” is a cron job you write against the free reads. There’s no session replay, no APM tracing, no uptime probing from twelve regions, and no retention tier you can negotiate. Logs and metrics live in their own namespaces on the same key and are metered separately — budget for them out of the same $5 rather than assuming they ride along free.

When the free tier of a specialist wins

Sentry’s Developer plan includes a monthly error quota at no cost, and it comes with the things listed above as gaps — source maps, alert rules, releases, an issue workflow. If your volume genuinely fits inside that quota and you only need error tracking, buy nothing: that’s the better deal and this page won’t pretend otherwise. Buy Sentry properly when you need minified browser traces, session replay or on-call routing — those aren’t things you rebuild on a weekend.

Where a metered API wins is the shape either side of that quota. Below it you pay cents instead of a plan fee; above it you pay per event instead of jumping a pricing tier; and across capabilities you get one bill instead of assembling error tracking from one vendor, log search from another and charts from a third — each with its own key rotation, its own free-tier ceiling and its own invoice. Honeybadger and Rollbar sit in the middle: cheaper than the enterprise tools, still a per-plan subscription rather than per-event.

For a small SaaS at this budget, the honest recommendation is to measure a month of real volume first, then decide. If it’s under a few thousand events, a free tier is fine. If it’s spiky — a bad deploy, a crash loop, a flaky third party — metered capture with free reads is the model that doesn’t punish you for a bad week.

References

Browse more errors developer guides