It’s 2:47 AM. Marcus, a senior backend engineer at a food delivery startup, is staring at a Slack alert on his phone.
The new “delivery zone health” dashboard — the one his team spent two sprints building and demoed to the VP last Friday — is showing a fat red banner: No index available on keyspace delivery_zones.
The feature worked perfectly in staging. The feature worked perfectly in the demo. The feature is now broken for every ops team member trying to monitor live delivery coverage across the city.
The query hadn’t changed. The data hadn’t changed. What changed was that, for the first time, someone actually opened the dashboard in production — and the N1QL query underneath it ran against a Couchbase collection that had never had an index created on it.
Marcus had written documents into that collection for months. Thousands of them. No errors, no warnings, no drama. He’d just never queried them before.
Here’s why this keeps happening to smart engineers: Couchbase lets you write documents without any index at all.
You can upsert a million records into a brand-new collection and every single operation will succeed beautifully. KV (key-value) operations — get, upsert, replace, delete by document key — bypass the query engine entirely. They go straight to the data service. No index required. Not even a primary one.
So you build your write path. You test it. It works. Green checkmarks everywhere. You move on.
Then, weeks or months later, someone adds a query — a SELECT that scans the collection to aggregate, filter, or report — and the whole thing detonates with a cryptic error that looks like Couchbase is gaslighting you.
The gap between “writing to a collection” and “querying a collection” is invisible until you cross it. The index-first mindset means you stop treating these as the same operation and start treating index creation as part of collection creation — not an afterthought you’ll add when something breaks.
N1QL (Non-First Normal Form Query Language — yes, that’s really what it stands for, no you don’t need to remember it) is Couchbase’s SQL-like query language.
It lets you write SELECT, WHERE, JOIN, and all the familiar constructs against your JSON documents. It’s powerful, flexible, and completely dependent on indexes to function.
When you run a N1QL query, Couchbase’s query engine needs a way to find the relevant documents without scanning every byte in the collection. An index is that map.
A primary index covers all documents in a collection and lets any query run — it’s the blunt instrument, great for development and small collections.
A secondary index covers specific fields and is what you want in production for performance.
When neither exists, Couchbase doesn’t silently degrade — it throws No index available on keyspace your_collection_name and refuses to run the query at all.
TTL (time-to-live) documents are one of Couchbase’s most elegant features. You write a document, attach an expiry, and Couchbase automatically deletes it when the clock runs out. No cron jobs, no cleanup scripts. Perfect for:
session tokens,
rate-limit counters,
health signals,
short-lived locks,
or anything that should naturally expire.
The trap is subtle. TTL collections almost always start life as write-only from the application’s perspective. You upsert a document for each active user session, each IoT sensor ping, each delivery courier’s last-known location. All KV operations. All fast. All index-free.
Then the product team asks for a dashboard. Or an alerting job. Or a report. And suddenly someone writes SELECT * FROM sensor_pings WHERE region = ‘us-east’ — and the collection that’s been humming along for two months in production, happily accepting thousands of writes per minute, refuses to answer a single read.
There’s a cousin to the TTL trap that’s even sneakier. A careful engineer implements a repository with both a write method and a read method — say, upsert_zone() and list_all_zones():
The write method gets wired up immediately.
The read method exists in the codebase, well-structured, fully tested with mocks, but has no actual caller yet. It’s infrastructure for a feature that’s coming next quarter.
Nobody creates the index, because why would they? The method isn’t called. Nothing is querying the collection. Everything is fine.
Three months later, a new engineer joins the team, sees the list_all_zones() method sitting there, wires it into the new reporting service, deploys to production — and gets paged at 2:47 AM. The code was always correct. The infrastructure was always missing.
The solution isn’t complex. It’s discipline.
Create the index alongside the collection in your setup or migration script. Same PR, same script, same line of review. If the collection exists, the index exists.
Add it to your verification step. If your setup script checks that collections are accessible, it should also check that indexes are online. An index that’s building won’t serve queries.
If you genuinely want to defer, leave a # TODO: add primary index when list_all() is wired up comment in the setup script — not in the repository class, in the infrastructure script. That’s where the fix lives.
Document the dependency in your PR. “This collection is write-only for now; index deferred to the reporting ticket” is a three-second comment that prevents a 3 AM incident.
The index-first mindset isn’t about being pedantic. It’s about recognising that Couchbase’s clean separation between KV and N1QL is a feature, not a loophole. Your KV path will be fast and index-free forever. Your N1QL path needs a map from day one — even if nobody’s reading the map yet.
Marcus added the primary index at 3:04 AM, redeployed, and watched the dashboard go green. He also added a rule to his team’s collection checklist: “If there’s a list_all method, there’s a primary index. No exceptions.”
The next deploy was on a Tuesday afternoon. Nobody got paged.
I’ve got a couple of great offers: FREE & discount access to my video courses - available for a limited time, so don’t wait too long!
🤖 The Agentic Engineering Bootcamp
Discount coupon AI_ASSISTED_ENG_14_N🔥 Modern Software Engineering: Architecture, Cloud & Security
Discount coupon RAKIA_SOFT_ENG_13🔐 Secure Software Development: Principles, Design, and Gen-AI
FREE coupon RAKIA_SECURE_APPS_12FREE coupon RAKIA_API_DESIGN_12
🐳 Getting Started with Docker & Kubernetes + Hands-On
FREE coupon RAKIA_DOCKER_K8S_12⚡ Master Web Performance: From Novice to Expert
FREE coupon RAKIA_WEB_PERF_13
💡 🧠 I break down the real-world engineering wisdom they don’t teach in tutorials. Join my newsletter or my YouTube channel, where I help working developers and engineers navigate the evolving tech landscape with clarity and confidence.

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.