FaunaDB Compound Indexes: Creation, Querying, and Pitfalls
Learn how to create and use a compound index in FaunaDB to filter and sort data efficiently, see a concrete FQL example, and avoid common pitfalls.
22 Jul 2025, 08:02 UTC

Why Compound Indexes Matter
When you query a collection in FaunaDB, the database can either scan every document or jump straight to the relevant rows using an index. A compound index lets you filter on one field and sort or filter on another in a single operation. This reduces the number of documents Fauna reads, cuts query cost to almost one per matching entry, and keeps write latency predictable.
Creating the Index
Indexes are first‑class objects in FaunaDB. They are defined in the console or via FQL with CreateIndex. Below is a concrete example that creates a compound index on the author and publishedAt fields of a books collection.
// Run in the FaunaDB console or via a client with admin privileges
CreateIndex({
name: 'books_by_author_date',
source: Collection('books'),
terms: [
{ field: ['data', 'author'] } // filter by author
],
values: [
{ field: ['data', 'publishedAt'] },
{ field: ['ref'] } // optional: return the reference
],
unique: false,
serialized: true
});
Key points:
termsdefine the fields you can filter on withMatch.valuesspecify the order or additional fields the index returns.serialized:truetells Fauna to store the index in a way that speeds reads but makes writes slightly slower.- Once created, an index’s
termsandvaluescannot be changed without dropping and recreating it.
Using the Index in a Query
With the index in place, you can retrieve all books by a specific author and sort them by publication date in a single, efficient query.
// Example query: get Alice’s books sorted newest first
Match(Index('books_by_author_date'), 'Alice')
.OrderBy(Index('books_by_author_date'))
.Limit(10); // optional pagination
Explanation of the steps:
Match(Index(...), 'Alice')filters the collection to documents whereauthorequals "Alice".- Because the index already contains
publishedAtas a value,OrderBycan sort without an extra scan. - The query cost is roughly
1per matched document, plus a tiny overhead for theOrderByoperation.
Understanding Query Costs
FaunaDB charges per index entry accessed. In the example above, if Alice has 50 books, the cost will be close to 50. A full‑collection scan would cost the size of the collection, which can be orders of magnitude higher. Monitoring the cost field in the query console helps confirm that the index is being used.
Limits and Common Mistakes
Immutability After Creation
Changing terms or values after creation forces a drop-and-recreate cycle. Dropping an index locks writes to the source collection until the new index is built, which can stall applications that rely on high write throughput.
Over‑Indexing
Each index consumes storage (about 1 MB per 10,000 entries) and adds a small write penalty. Creating indexes that are never used can inflate costs unnecessarily. Review query patterns before adding new indexes.
Missing Serialized Flag
If you expect heavy read traffic, omitting serialized:true will keep writes faster but make reads slower. Balance your read/write mix accordingly.
Wrong Field Paths
Fauna stores document fields under data. A common error is specifying author instead of data.author in terms. Such misconfigurations cause the index to be empty and queries to fall back to a full scan.
Practical Checklist Before Deployment
- Verify that the index’s
termsandvaluesmatch your query patterns. - Set
serialized:trueif the index will be read often. - Run a test insert and query to confirm the cost is low.
- Monitor storage usage:
fauna index listshowssizeper index. - Document the index purpose so future developers know why it exists.
Diagram
The following diagram labels illustrate the flow of a compound index query in FaunaDB.
| Collection | Index | Query | Result |
|---|---|---|---|
| books | books_by_author_date | Match + OrderBy | Filtered & sorted list |
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.