How to monitor Turso / libSQL edge databases for SaaS apps
Your API returns 200 while every query times out against Turso. That is a database false green: the app process is alive but libSQL at the edge is unreachable or lagging. Monitor Turso database uptime honestly by splitting app liveness from database reachability, using read-only probes, and pointing StillOnline at a public /ready URL — not a raw Turso endpoint that needs a secret Bearer token.
Quick answer
Turso exposes GET /health on your database HTTPS URL, but external uptime tools should not store your DB Bearer token. Add GET /ready on your app with a read-only libSQL ping (SELECT 1, 3–5 second timeout). Return 503 when the database fails. Point StillOnline at https://api.yourapp.com/ready. Free: one URL, five-minute interval, HTTP status code only.
For generic health URL setup, read our health check quickstart. For Postgres-style patterns, see Neon and PlanetScale database uptime checks.
1. Split app health from database reachability
Three layers matter: L1 your API process, L2 libSQL connectivity from that process, L3 Turso platform or regional edge health. StillOnline on your public /ready covers L1–L2 from outside.
| Probe target | What it proves | StillOnline? |
|---|---|---|
| GET /health (app only) | Process accepts HTTP | Yes, but misses DB |
| GET /ready (app + libSQL ping) | Customers can query data | Yes — preferred |
| Turso GET /health (direct DB URL + Bearer) | Database HTTP layer up | No — secrets in monitor config |
| api.turso.tech platform check | Vendor control plane | Separate concern |
Do: monitor the URL that means users cannot load data when it fails. Do not: paste Turso database tokens into StillOnline.
Wrap libSQL checks inside your app — same pattern as connection pool health checks.
2. Run safe read-only probe queries
Probes must never write, migrate, or lock tables. Use SELECT 1 or a tiny read against metadata you already cache. Cap total handler time at 3–5 seconds.
app.get("/ready", async (req, res) => {
try {
await Promise.race([
client.execute("SELECT 1"),
new Promise((_, r) => setTimeout(() => r(new Error("timeout")), 5000))
]);
return res.json({ status: "ok", checks: { database: "ok" } });
} catch (e) {
return res.status(503).json({ status: "down", checks: { database: "fail" } });
}
});
Do: reuse the same libSQL client pool your handlers use. Do not: open a new connection per probe without limits.
Keep GET /health separate: return 200 with version and timestamp only. StillOnline Free evaluates HTTP status codes, not JSON fields — return 503 on /ready when libSQL throws or times out.
curl -sS -o /dev/null -w "%{http_code}\n" https://api.example.com/ready
3. Set latency thresholds for edge replicas
Edge SQLite targets low milliseconds inside the region, but your monitor runs from another geography. Document p95 latency from the probe region, not from inside the datacenter.
| Signal | Healthy pattern | Investigate when |
|---|---|---|
| /ready latency | Stable p95 under your SLO | Sustained 2× baseline for 3+ probes |
| Embedded replica sync | Lag within minutes | CLI turso db show shows rising lag |
| HTTP 503 rate | Zero on /ready | StillOnline debounced DOWN |
StillOnline Free debounces two failed probes before DOWN on a five-minute cadence. Latency needs logs or APM; the monitor proves reachability.
4. Wire StillOnline through your API layer
Register the same HTTPS host your customers hit — typically https://api.yourproduct.com/ready. StillOnline does not execute SQL or read Turso tokens; it sends GET and reads the status code.
- Sign in at stillonline.tech/app and create a project.
- Add a check with full
/readyURL, method GET, expect 200. - Exclude /ready from auth middleware — monitors send no JWT.
- Wait 2–3 probe cycles after deploy before judging flakiness.
- Enable owner alerts — Free allows one channel.
Do: label the status page component "Database" or "API." Do not: monitor localhost or internal libsql:// URLs.
Compare with health endpoint design for 200 vs 503 semantics.
5. Write status page copy when DB is degraded
When /ready returns 503, your public status page should say what users feel — slow saves, login errors, read-only mode — not "libSQL heartbeat failed."
| State | User-facing title | Body hint |
|---|---|---|
| Degraded | Elevated API latency | Some requests slower; data safe |
| Major outage | Database unavailable | Cannot load or save data; investigating |
| Monitoring | Third-party database provider | Link Turso status only when platform-wide |
- Draft templates now — before the first 3 a.m. page.
- Match StillOnline component name to the check you registered.
- Post an update within 15 minutes of confirmed DOWN.
- Resolve with root cause category — app deploy, pool exhaustion, vendor incident.
- Re-test /ready from outside before marking resolved.
Do: rehearse DB stop in staging and watch StillOnline flip red. Do not: claim "all systems operational" while /ready still returns 503.
What's next
You split app and database probes, added a read-only libSQL ping, registered /ready in StillOnline, and drafted honest status copy. Add a second check for your marketing site on Pro, watch Turso platform status during widespread reports, and document which URL your on-call treats as canonical.
Open the StillOnline dashboard, paste your /ready URL, and enable the alert channel you read during incidents.
Related guides
- Health check URL quickstart
- Neon and PlanetScale database uptime checks
- Database connection pool health check
- Health endpoint design
FAQ
Should StillOnline probes hit Turso directly or via /ready?
Via /ready on your app. Direct Turso GET /health needs a Bearer token — fine for internal cron, risky in StillOnline config. Map database failure to HTTP 503 on /ready.
How is Turso monitoring different from Neon with StillOnline?
Neon is serverless Postgres; Turso is SQLite at the edge with embedded replicas. Both use app-layer /ready with a lightweight query; Turso adds edge latency variance.
What read-only query should /ready use for StillOnline?
SELECT 1 is enough for reachability. Timeout the check at 3–5 seconds and return 503 on failure.
503 or 200 when Turso blips briefly — what should StillOnline see?
Return 503 on /ready when libSQL is unreachable. StillOnline Free reads status codes only.
Should I watch Turso platform status alongside StillOnline?
Yes for vendor-wide incidents. Your /ready probe still matters for tenant-specific failures platform status will not show.
What latency should trigger investigation with StillOnline?
Document baseline p95 from your probe region. Investigate sustained doubling — not a single slow probe from far away.