Diagnosing FaunaDB Query Performance Degradation: A Practical Guide
A step‑by‑step diagnostic guide for FaunaDB query performance issues: identify symptoms, run targeted checks, apply fixes (indexes, consistency, pagination, TTL, backoff), and verify results with concrete FQL examples.
17 Aug 2026, 15:33 UTC

Problem and Takeaway
FaunaDB queries can slow down, return stale data, fail on pagination, or abort transactions. The root causes are usually missing indexes, weak read consistency, oversized pages, TTL expiration, or write conflicts. This guide gives a repeatable diagnostic flow: identify the symptom, run a targeted check, apply the fix, and verify the result.
Recognizable Conditions
| Symptom | Likely Cause | Quick Indicator |
|---|---|---|
| High latency on reads | Missing secondary index on the queried field | Query scans entire collection; Explain shows full collection scan |
| Stale results after a write | Read consistency level set to eventual (default) | Repeated reads return older version until propagation completes |
| Pagination fails or returns incomplete results | Default page size (64) exceeded or cursor misuse | after token missing or pageSize too large |
| Document not found errors | TTL expiration removed the document | Document’s ts field older than TTL window |
Transaction aborts with contention errors | Concurrent writes to same document | High abort rate in dashboard metrics |
Ordered Diagnostic Checks
- Run
Explainon the slow query. In Fauna Shell or driver, callExplain(query). Look forscanvsindexin the plan. A scan indicates missing index. - Check read consistency setting. Inspect the driver options or query call:
consistency: 'strong'forces linearizable reads. Default iseventual. - Inspect pagination parameters. Verify
pageSize(max 100,000) and that you pass theaftercursor from the previous page. - Review TTL configuration. In the collection schema, check
ttl_daysor per-documentttlfield. Expired documents are purged asynchronously. - Measure transaction conflict rate. Open the Fauna dashboard → Metrics → Transaction Conflicts. A rising trend signals contention.
Fixes Tied to Findings
1. Missing Index → Create Secondary Index
Run this FQL in Fauna Shell (requires admin or server key):
CreateIndex({
name: "users_by_email",
source: Collection("users"),
terms: [{ field: ["data", "email"] }],
values: [{ field: ["ref"] }]
})
Placeholders: replace users with your collection, email with the queried field. Expected check: re-run Explain; plan should show index: "users_by_email". Risk: index build adds write latency for a few minutes; schedule during low traffic.
2. Stale Reads → Enable Strong Consistency
In your application code (example using JavaScript driver):
const result = await client.query(
q.Get(q.Match(q.Index("users_by_email"), "[contact removed]")),
{ consistency: "strong" }
);
Verification: after a write, immediate read returns the new version. Monitor the Consistency metric in the dashboard; it should show strong for the query.
3. Pagination Failures → Adjust Page Size or Use Cursors
Set an explicit pageSize (e.g., 500) and always pass the after token:
const page = await client.query(
q.Paginate(q.Match(q.Index("users_by_email")), { size: 500, after: lastCursor })
);
Check: each response includes a new after cursor; no before unless you need reverse pagination.
4. TTL Expiration → Extend or Disable TTL
Update collection TTL (requires admin key):
Update(Collection("sessions"), {
ttl_days: 30 // was 7
})
Caution: TTL expiration is irreversible. Backup critical data before changing. Verify by querying a document’s ttl field: Select(["data", "ttl"], Get(Ref(Collection("sessions"), "123"))).
5. Transaction Conflicts → Implement Exponential Backoff
Wrap transaction in a retry loop (pseudo-code):
async function runWithBackoff(fn, maxRetries = 5) {
for (let i = 0; i < maxRetries; i++) {
try { return await fn(); }
catch (e) {
if (e.name !== "Contention") throw e;
await new Promise(r => setTimeout(r, Math.pow(2, i) * 50));
}
}
throw new Error("Max retries exceeded");
}
Alternative: enable history_days on the collection to retain prior versions for conflict inspection.
Escalation Criteria
- After index creation, latency remains > 200 ms for 95th percentile → engage Fauna support with
Explainoutput. - Strong consistency causes cost spikes > 2× baseline → evaluate read‑only replicas or caching layer.
- Pagination still fails with correct cursors → possible driver bug; file a ticket with driver version and request logs.
- TTL adjustments do not prevent deletions → verify background task schedule; may require manual document re‑creation.
- Conflict rate > 10 % of writes after backoff → consider data model redesign (e.g., split hot documents).
Limitations and Verification
Index creation is asynchronous; the Explain plan may still show a scan for a few minutes. Use the dashboard’s Index Build Progress to confirm completion. Changing consistency level affects billing; test in a staging environment with a representative workload before production rollout. TTL changes only affect new documents; existing documents keep their original expiration unless updated individually.
Practical verification checklist:
- Run a benchmark query (e.g.,
Map(Paginate(Match(Index("users_by_email"))), Lambda("ref", Get(Var("ref"))))) before and after index creation; compare execution times. - Confirm
Explainshows the new index in the plan. - Observe the
Consistencymetric after settingstrong. - Monitor transaction conflict rate for 24 hours after backoff implementation.
Diagram Labels
- Symptom → Cause Table
- Explain Plan Output
- Index Creation Flow
- Backoff Retry Loop
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.