Data
NoSQL
NoSQL is four different tools wearing one label. We help you tell them apart — and tell you honestly when you should have stayed with Postgres.
Overview
NoSQL is not a database; it is a category, and a loose one. The name covers every store that steps away from the relational model — no fixed table schema, often no joins, and frequently a different bargain with consistency. The common thread is that each family trades one or more of the guarantees a relational database gives you by default in exchange for something specific: flexibility of shape, raw speed on a narrow access pattern, horizontal scale across many machines, or a data model that fits a problem relational tables handle awkwardly. Understanding NoSQL means understanding those trades, because you are always giving something up to get something.
There are four families, and they are genuinely different tools. Document stores (MongoDB) hold self-contained records as JSON-like documents, good for data whose shape varies or evolves. Key-value stores (Redis, DynamoDB) map a key straight to a value at very low latency, the workhorse of caching, sessions, and counters. Wide-column stores (Cassandra, Bigtable) spread enormous, write-heavy datasets across many nodes with tunable consistency, built for scale relational primaries cannot reach. Graph databases (Neo4j) make relationships first-class, so traversals across a densely connected network — who knows whom, what depends on what — stay fast where SQL joins would crawl. Lumping these together under one word causes more bad decisions than almost anything else in data architecture.
Our position is unfashionable and, we think, correct: a relational database — PostgreSQL — is the right default for the large majority of applications, and NoSQL is something you add deliberately, for a specific access pattern it genuinely serves better, not something you reach for out of habit or fashion. The most common reason teams pick NoSQL — "we might need to scale" — is almost never a good enough reason to surrender joins, transactions, and ad-hoc queries on day one. We start relational, keep the store of record correct and queryable, and introduce a NoSQL store when the evidence points at a real problem that store is genuinely built to solve.
Best for — A specific, well-understood access pattern that a relational database serves badly — flexible documents, low-latency key-value lookups, massive write-heavy scale, or relationship-heavy traversal — added deliberately alongside a relational store of record, not chosen as a default because it sounds modern.
Why teams choose NoSQL
The right family for the access pattern
The value of NoSQL is entirely in matching the store to the shape of the problem: a document store for varied records, a key-value store for hot lookups, a wide-column store for write-heavy scale, a graph for relationships. Chosen this way, the fit is genuine and the payoff is real. We help you pick the correct family — including "none of them, use Postgres" — rather than defaulting to whichever one is fashionable.
Horizontal scale where you truly need it
Several NoSQL stores are built to spread data and writes across many commodity machines by design, not as an afterthought. For the workloads that genuinely reach that scale — huge event and telemetry volumes, global low-latency key-value access — that horizontal model does something a single relational primary cannot, and does it without heroics.
Schema flexibility for data that resists structure
Document stores let records carry different fields without a migration for every change, which is genuine value when the domain is genuinely varied — third-party payloads, per-tenant custom shapes, rapidly evolving product data. We treat that as a precise tool for the unstructured parts, not a licence to abandon data design.
Why businesses choose NoSQL
- You have a specific access pattern — not a vague fear of future scale — that a relational database demonstrably serves badly, and you want the correct NoSQL family chosen for it by people who understand all four.
- You want honest counsel about whether you need NoSQL at all, from a team that will happily talk you back to Postgres and JSONB when that is the right answer — which it often is.
- You are already running a NoSQL store that is causing pain — consistency surprises, a data model that no longer fits your queries, runaway cost — and you need someone to diagnose whether to fix the model or migrate off it.
- You want polyglot persistence done deliberately: a relational store of record with a NoSQL store added for the one job it genuinely serves better, wired together cleanly, rather than a sprawl of databases accumulated by habit.
What we build with NoSQL
The capabilities this technology is genuinely strong at — and what we most often build with it.
Document stores — for varied, evolving records
Document databases such as MongoDB hold each record as a self-contained JSON-like document, so structure can vary between records and evolve without a migration for every change. They fit data that is genuinely document-shaped — content, catalogues, per-tenant custom fields, third-party payloads — and read naturally when you fetch a whole record at once. We use them where the flexibility is real value, and we are candid that for many teams Postgres’s JSONB already covers this ground without a second database.
Key-value stores — for caching, sessions, and counters
Key-value stores such as Redis and DynamoDB map a key directly to a value at very low latency, which makes them the standard tool for caching, session storage, rate limiting, leaderboards, and real-time counters. This is the most common and least controversial reason to add NoSQL: a hot lookup a relational database would labour over becomes a sub-millisecond operation. It almost always lives alongside your relational store, not instead of it.
Wide-column stores — for massive write-heavy scale
Wide-column stores such as Cassandra and Google Bigtable spread enormous datasets across many nodes with tunable consistency and no single write bottleneck, built for append-heavy, high-throughput workloads — telemetry, event logs, time-series at a scale a single relational primary cannot hold. The catch is that you model the data around your queries in advance; they are unforgiving of access patterns you did not design for, so they suit problems whose read shape is known and stable.
Graph databases — for relationship-heavy data
Graph databases such as Neo4j make relationships first-class, storing nodes and the edges between them so traversals across many hops stay fast and the queries stay readable. They shine where the value is in the connections — social graphs, recommendation paths, dependency and impact analysis, fraud-ring detection — precisely the queries that turn into slow, tangled recursive joins in SQL. For a densely connected domain, the right model is a graph, not a table.
Horizontal scaling and sharding
Distributing data across nodes is where several NoSQL stores earn their reputation. Sharding by a partition key spreads both data and load, and replication keeps copies for availability. We design the partition key with care, because it is the single most consequential decision in a distributed store — a poorly chosen key produces hot partitions and uneven load that no amount of hardware fixes — and it is very hard to change once data has landed.
Consistency models done with eyes open
The CAP theorem says that when the network partitions, a distributed store must choose between consistency and availability, and different NoSQL stores make that choice differently — some tunable per query. We make that choice explicit for each piece of data: where eventual consistency is genuinely fine, we take the availability; where a read must reflect the latest write, we say so and design for it, rather than discovering the difference in a production incident.
Use cases
Caching and session layer alongside Postgres
A Redis key-value layer in front of a relational store of record — caching expensive query results, holding sessions and rate-limit counters, and serving leaderboards and real-time state at a latency the database cannot match. The canonical, well-earned use of NoSQL: a fast specialist doing the one job it is best at, next to a correct relational primary.
High-volume telemetry and event storage
Sensor, IoT, and event data arriving at a volume and write rate a single relational primary cannot sustain, landed in a wide-column store such as Cassandra where writes distribute across nodes and the query shape is known in advance — with the relational database kept for the transactional core it does best.
Flexible document-shaped content
Catalogues, content, and per-tenant records whose fields genuinely vary and evolve, held in a document store where new shapes need no migration — used where the flexibility is real, and weighed honestly against keeping the same data in Postgres JSONB to avoid running a second database.
Relationship and graph traversal
Recommendation engines, social and organisational graphs, dependency and impact analysis, and fraud detection, where the questions are about paths and connections across many hops. A graph database such as Neo4j answers these in fast, readable traversals that would be slow, brittle recursive joins in SQL.
When NoSQL is the right choice
- Your data is genuinely document-shaped — self-contained records whose fields vary between instances or evolve quickly — and you are not constantly querying across records in ways that want joins. A document store lets the shape flex without a migration for every change, and that flexibility is real value when the domain actually behaves that way.
- You have a narrow, high-volume access pattern that a key-value store serves at a latency and cost a relational database cannot touch — session storage, caching, rate limiting, leaderboards, real-time counters. This is the least controversial and most common good reason to add NoSQL, and it usually sits alongside Postgres rather than replacing it.
- You are dealing with massive, write-heavy, append-oriented data at a scale a single relational primary genuinely cannot hold — sensor and IoT telemetry, event streams, time-series at billions of rows a day — and you can model your queries in advance. A wide-column store is built for exactly this, where horizontal write scaling is the whole point.
- Your problem is fundamentally about relationships — social graphs, dependency networks, recommendation paths, fraud rings — and the value is in traversing many hops of connections. A graph database makes those traversals fast and the queries readable, where the equivalent recursive SQL joins become slow and unwieldy.
- Wrong for: your store of record when the data is relational and correctness matters — orders, accounts, payments, inventory. "We might scale someday" is not a reason to give up transactions, foreign keys, joins, and ad-hoc queries you will certainly need. Start with Postgres; the day you actually outgrow it is a good problem you can solve then, with evidence.
NoSQL: pros and cons
Strengths
- Each family is excellent at its own job: document stores for flexible records, key-value for microsecond lookups, wide-column for write-heavy scale, graph for relationship traversal. Matched to the right access pattern, a NoSQL store outperforms a relational one at the thing it was built for, often dramatically.
- Horizontal scaling is native to several stores — data and writes distribute across nodes by design, so you scale by adding machines rather than by buying a bigger single server. For the workloads that actually reach that ceiling, this is a genuine capability relational primaries lack.
- Flexible schemas remove migration friction for genuinely variable data: documents can differ field by field and evolve without a coordinated schema change, which suits fast-moving or heterogeneous data honestly better than rigid tables.
- Tunable consistency and availability let some stores keep serving reads and writes through partitions and node failures, trading strict consistency for uptime where the workload can tolerate it — a deliberate, useful choice for the right problem.
Trade-offs
- Weaker consistency and transactions — and it varies by store, which is its own trap. Many NoSQL databases offer only eventual consistency by default, so a read can return stale data just after a write; multi-record transactions are limited, absent, or costly. If your data needs atomic, correct updates across records, this is a serious loss, and teams routinely underestimate how much they relied on it.
- No flexible joins and poor ad-hoc querying. NoSQL stores are fast on the access patterns you designed for and awkward-to-impossible on the ones you did not. The moment a stakeholder asks a question your data model did not anticipate, you are exporting to somewhere else to answer it — where in Postgres it would have been a five-minute query.
- Data modelling locks you to known access patterns. NoSQL demands you design the data around how you will read it, up front. That is fine until the access patterns change — and they always do. A relational schema absorbs new queries; a denormalised NoSQL model often needs re-modelling and re-migration when the questions shift.
- Polyglot persistence adds real operational weight. Every additional store is another system to deploy, secure, back up, monitor, patch, and reason about consistency across — plus the application code that keeps two sources of truth in step. That complexity is a permanent tax, and it is why we add a NoSQL store only when the workload genuinely justifies carrying it.
Architecture
We almost always design a polyglot architecture rather than an all-NoSQL one: a relational store of record — Postgres — holding the data that must stay correct and queryable, with a NoSQL store added for the specific access pattern it genuinely serves better. That keeps a single source of truth for the data that matters and confines the NoSQL store to the job it was chosen for. The alternative — pushing everything into a document or wide-column store because one part of the system needed it — is how teams end up unable to answer ordinary questions about their own data.
Within a NoSQL store, the data model is designed backwards from the queries, because that is how these databases demand to be used. For a wide-column store we choose the partition key and clustering order around the exact reads we need to serve, accepting that this locks the model to those patterns. For a document store we decide deliberately what to embed versus reference, trading query simplicity against duplication and update cost. For a graph we model the entities and edges that traversals will follow. And we design the consistency boundary explicitly — what may be eventually consistent, what must not be — rather than inheriting whatever the default happens to be.
Performance
NoSQL performance is real but narrow: these stores are extremely fast on the access patterns they were modelled for, and poor to unusable on the ones they were not. A key-value lookup by key is microseconds; a wide-column read along the partition key is very fast at enormous scale; a graph traversal across a connected neighbourhood outruns the equivalent joins. The performance comes precisely from designing the data around those reads. Ask a question the model did not anticipate and you are into full scans, application-side joins, or exporting the data elsewhere to answer it — the exact operations these stores are bad at.
So we tune by getting the data model right first, because in NoSQL the model is the performance. That means choosing partition and sort keys against real query patterns, avoiding hot partitions that concentrate load on one node, and being honest about which queries the design does not support — before they are needed rather than after. Where a store offers tunable consistency, we set the read and write levels per operation to buy latency where correctness allows, and we measure against representative data volumes rather than a near-empty test cluster that hides every distribution problem.
Security
The NoSQL security story is more uneven than the relational one, and that unevenness is itself a risk. Several of the most damaging public data breaches came from NoSQL stores left open to the internet with authentication disabled by default — a configuration failure, not a database flaw, but one these systems have historically made easy. We treat secure configuration as the first job: authentication and authorisation on from the start, the store bound to a private network and never exposed publicly, role-based access with least privilege, TLS in transit, and encryption at rest.
Injection matters here too, in a different shape from SQL. Document-store queries built from unsanitised input allow query-operator injection, so we construct queries safely and validate input at the boundary rather than trusting it. Because schemas are flexible, we push validation into the application and, where the store supports it, into schema validation rules — flexibility is not an excuse to let malformed or malicious data in. And backups are encrypted, access-controlled, and restore-tested, because a distributed store you have never practised recovering is a recovery plan you do not actually have.
Scalability
Horizontal scale is the headline reason teams reach for NoSQL, and for the workloads that genuinely need it, it is real: wide-column and distributed key-value stores spread data and writes across many nodes, so you grow by adding machines rather than replacing one with a bigger one. When your write volume genuinely exceeds what a tuned single primary can hold, this is the capability that solves it, and no amount of relational tuning substitutes for it.
But we are blunt about the trade, because it is the most misused argument in data architecture. That horizontal scale is bought with weaker consistency, no flexible joins, and a data model welded to your current access patterns — and most teams who invoke "we need to scale" have not yet outgrown a single Postgres primary with good indexing and read replicas, which carries none of those costs. The honest sequence is to scale relationally as far as it goes, which is much further than most expect, and to move a specific workload to a distributed NoSQL store only when the evidence — real volumes, real limits — says the relational option is genuinely exhausted. Adopting distributed-database complexity in advance of that evidence is a cost you pay every day for a problem you may never have.
NoSQL integrations & ecosystem
The technologies we most often pair with it — each links to how we work with it.
How we work
We start by challenging the premise. Before adding any NoSQL store we ask what specific access pattern justifies it and whether a relational database — Postgres, often with JSONB or an extension — already serves that pattern well enough. A great many "we need NoSQL" conversations end with a better-indexed Postgres and no second database, and that is a good outcome, not a failure. When a NoSQL store is genuinely the right tool, we pick the family from the access pattern rather than from familiarity or fashion, and we say plainly which one and why.
From there the work is data modelling done backwards from the queries, because in NoSQL the model is the whole game and it is expensive to change later. We design the partition keys, embedding decisions, or graph structure around the real reads, set the consistency boundaries explicitly, and secure the store properly from the first day. The engineers who design it operate it, which is what we mean by operating what we build — so we optimise for the on-call reality of a distributed store: monitoring, backups that restore, and a clear picture of which questions the model can and cannot answer.
The service behind it
Delivered throughData EngineeringWhat we build with NoSQL
The disciplines this technology most often shows up in — from a first build to taking over and stabilising an existing one.
How we deliver
- 01
Discover
We map the system, the constraints and the business it serves — including the parts nobody documented.
Architecture brief
- 02
Architect
Decisions get made, written down and defended before a line of production code exists.
Decision records
- 03
Build
Short cycles against working software. You see progress in the product, not in a status deck.
Shipping increments
- 04
Operate
Monitoring, incident response and iteration. The system is alive, so the engagement is too.
Runbooks & SLOs
Industries we use NoSQL in
Domain knowledge changes what gets built. A few of the sectors we know before the first meeting.
Also in Data
Why teams choose us for NoSQL
We know all four families, not just the fashionable one
Most teams reach for whichever NoSQL store they have used before and bend the problem to fit it. We choose the family from the access pattern — document, key-value, wide-column, or graph — and we are equally willing to conclude that none of them fits and you should stay relational. That breadth is the difference between a store that fits and one you fight for years.
We will talk you out of it when it is wrong
The most valuable advice we give about NoSQL is often "you do not need it". "We might need to scale" is not a reason to surrender joins, transactions, and ad-hoc queries. We start relational, add a NoSQL store only for an access pattern that genuinely warrants it, and we would rather protect you from complexity than sell it to you.
We operate what we build
A distributed store is materially harder to run than to demo — hot partitions, consistency surprises, backups that must restore across nodes. Because we run the databases we design, we optimise for that on-call reality from the first day, not the benchmark: secure configuration, real monitoring, and an honest map of what the data model can answer.
Senior engineers only
The data model in a NoSQL store is welded to your access patterns and brutally expensive to change once data has grown on it — exactly the kind of decision juniors get wrong in ways that surface years later under load. The people designing your partition keys and consistency boundaries have made these choices many times before.
Typical timeline
- 01
Discovery and store selection
One to two weeks understanding the access patterns, volumes, and consistency needs, and deciding honestly whether NoSQL is warranted at all and, if so, which family — so the choice is settled on evidence before anything is built.
- 02
Data modelling and design
Modelling the store backwards from its queries — partition and sort keys, embed-versus-reference decisions, or graph structure — and defining the consistency boundaries explicitly, because the model is the hardest thing to change once data has landed on it.
- 03
Build and integration
Implementing the store alongside the relational store of record, wiring the application to keep sources of truth in step, and putting monitoring, secure configuration, and backups in place from the start rather than after the first incident.
- 04
Load validation and handover
Validating against representative data volumes to surface hot partitions and consistency edge cases before production, restore-testing backups, and documenting which queries the model supports and which it does not so your team can own it.
How pricing works
- Fixed-scope engagements for well-defined work — a data-store selection and design, a caching or event-storage layer built alongside an existing Postgres, or a modelling exercise for a specific NoSQL store — quoted once we understand the access patterns and volumes.
- Monthly senior engagement for ongoing product work where the data layer evolves with the application and you want continuity of the people who designed it, rather than a one-off deliverable.
- Focused audits and rescues for NoSQL deployments in trouble — consistency surprises, a data model that no longer fits the queries, hot partitions, or runaway cost — priced by the assessment, including an honest recommendation on whether to fix the model or migrate off the store.
Hire NoSQL engineers
Need NoSQL capacity on your own team? We embed named senior engineers into your existing team — reporting to your leads, working in your rituals — so you add capacity without a hiring cycle.
Hire NoSQL engineersCommon questions
Should we use NoSQL or a relational database like PostgreSQL?
For most applications, start relational. PostgreSQL should be your default store of record because it keeps its options open: joins, transactions, foreign keys, and ad-hoc queries you will certainly need but cannot always predict. NoSQL is something you add deliberately for a specific access pattern a relational database serves badly — caching, huge write-heavy telemetry, relationship traversal, or genuinely document-shaped data. The trap is choosing NoSQL as a default because it sounds modern, or on the strength of "we might need to scale". That single line has produced more regretted architectures than almost anything else, because it trades away real, daily capabilities for a scaling problem most teams never actually hit.
What are the four types of NoSQL database and when does each fit?
Document stores (MongoDB) hold self-contained JSON-like records and suit data whose shape varies or evolves. Key-value stores (Redis, DynamoDB) map a key straight to a value at very low latency and are the standard tool for caching, sessions, and counters. Wide-column stores (Cassandra, Bigtable) distribute massive, write-heavy datasets across many nodes and suit telemetry and event data at a scale a single relational primary cannot hold. Graph databases (Neo4j) make relationships first-class and suit relationship-heavy problems — social graphs, recommendations, fraud rings — where the value is in traversing many hops of connections. They are genuinely different tools; the single most common NoSQL mistake is treating them as interchangeable.
Is NoSQL faster than a relational database?
Only on the access patterns it was designed for, and that caveat is the whole story. A key-value lookup by key or a wide-column read along the partition key is extremely fast at scale, because the data was modelled precisely around that read. Ask a question the model did not anticipate and NoSQL is slow to unusable — you end up scanning everything, joining in application code, or exporting the data elsewhere to answer it. A well-indexed relational database is fast across a far wider range of queries, including ones you had not thought of yet. NoSQL buys narrow, exceptional speed at the price of that flexibility, so the honest answer is: faster at its one job, slower at everything else.
What is the CAP theorem and why does it matter for NoSQL?
The CAP theorem says that when the network between nodes partitions — and in a distributed system it eventually will — a store must choose between consistency (every read sees the latest write) and availability (every request still gets an answer). It cannot guarantee both during a partition. This matters because many NoSQL stores are distributed and default to availability with eventual consistency, meaning a read just after a write can return stale data. For a cache or a like-count that is fine; for a bank balance or an inventory count it is not. We make that choice explicit for each piece of data rather than inheriting whatever the store defaults to, because the difference is one you never want to discover in a production incident.
We already use MongoDB and it is becoming painful — what now?
This is a common rescue, and the pain usually traces to one of a few causes: a data model that fitted the original queries but not the ones you now run, consistency assumptions that no longer hold, hot partitions from a poorly chosen shard key, or cost that has climbed as data grew. The first job is diagnosis — whether the problem is fixable by re-modelling within Mongo, or whether the data was relational all along and belongs in Postgres, where JSONB already covers much of what document stores are used for. We give an honest recommendation either way, including migrating off when that is genuinely the right call, rather than defending a choice that is no longer serving you.
Building on NoSQL?
A technical conversation with the engineers who would do the work. If we are not the right fit, we will say so on the call.