Never believe that any tool is good or bad. That's always going to be a generalization, and therefore wrong. Learn as many tools as possible, and know which use cases they're good at and which use cases they're bad at. If someone implies the tool is bad for all use cases, know that we all live in our own bubbles and are ignorant about the plethora of other use cases that exist in the world.
> Eg I'm fairly confident to generalise and say that for most beginners in 2025 picking Python is a better choice than PHP or Cobol.
Limiting choices to “pick one” seems contrived. Beginners should learn to program and think like programmers, which means learning multiple languages and tools. Programming languages have far more in common with each other than not and the sooner a beginner thinks of themselves as a problem solver rather than a Python programmer the better.
> Of course, you can come up with some contrived scenarios where the beginner would be better served with Cobol.
I don’t think looking at job opportunities and pay qualify as “contrived scenarios.” PHP has a huge footprint in web applications and every beginner steered away from PHP to the saturated Python world forgoes a lot of opportunity. And again nothing prevents learning both. COBOL as usual gets trotted out as the dinosaur, but right now in the current tech job apocalypse knowing COBOL would get a lot more job offers than knowing Python.
IMO key value stores tend to live in the space between a third normal form ultra relational UML diagram database like the college textbooks assure you exist and a high chaos cowboy document storage system like mongodb.
They enable you to make a lot of things up as you go and iterate on your design. I like them because they remove a lot of ceremony around letting me get on with persisting things without having to ALTER TABLE or CREATE TABLE and all that entails. At the same time, they're constrained and often organized in a way that storing big ol' json blobs aren't. I like them for doing multiplayer gamedev things.
The relational normal forms are actually pretty practical.
But you are right that in practice you sometimes want to deviate from them. And then it is still useful to be aware of what the normal form of your database _would_ be, and how you are deviating.
Similarly to how sometimes you might want to manually unroll a loop in your code, and it's still useful to keep in mind conceptually how the original loop would have looked like.
Fundamentally this isn't a theoretical limitation of the relational model, instead it is a historical artefact that "doesn't have to be that way".
Systems like Kubernetes or Azure Resource Manager show how this ought to have been implemented: Declarative resource definitions via an API with idempotency as a core paradigm.
I.e.: Instead of the web developer having to figure out the delta change between two schema versions, they should just "declare" that they want some specific schema. This could happen with every code deployment, with most such changes doing nothing. If the schema does change, then it's up to the database engine to figure out how to make it happen, much like how a Kubernetes cluster reconciles the cluster state with a deployment definition.
KV stores become popular because they do this implicitly, with no explicit schema at all.
Relational databases (or even KV stores!) could instead use an explicit schema with automatic reconciliation instead of manual delta changes implemented by developers.
TL;DR: The tooling is bad. KV is an over-reaction to this, but instead we just needed better tools.
Django (python web framework) migrations have worked similar to this for well over a decade: You modify the models, then generate the migrations from the models and commit those.
The changes aren't generated on the fly at runtime because it can prompt you for things it suspects or can't figure out, for example if you rename a column the naive way would be an add+delete, which erases data. If the types are the same, it checks whether you wanted that or a rename, and generates the appropriate migration.
I make my own tools. KV makes it really easy to stop having to care about the database layer really early in a project and live entirely in code. It's fine.
Is he right that this imaginary future product might be a better solution than current KV datastores? Maybe - he makes a good case, it certainly sounds worth pursuing, and he can point to a case where it sort of works well already (FoundationDB).
Doen that imply that you should give up on KV datastores today, when this product category he's asking for barely exists? No, obviously not.
Like most articles that make strong assertive statements like this, it's an oversimplification. Every tool has its place. The author clearly wants to use SQL, and seems to have a problem that would benefit from it, so they should use a SQL DB and not try to use a KV DB.
He’s basically just asking for SQL without the query planner because it’s obnoxious and how often do you have unconstrained arbitrary queries hitting the database that you don’t have the chance to vet anyways? The database is hidden behind applications 100% of the time; why is this a predominant design use case
KVs give you this behavior, they just drop everything else with it
You usually want a query planner, else you'll end up writing a query planner yourself to produce efficient queries.
What is sometimes needed is query plan stability, lack of surprises, and influencing the planner. This is very attainable in the existing SQL databases and is a core feature of the older ones, like Oracle.
I’m not really talking about eliminating the query compilation step — that’s always useful. The dynamic query compilation however — the planner executing on every submitted query — is generally less so but fundamental to RDBMS goals. Query plan stability is the point — if you’re stabilizing the query planner, then you’re explicitly opting out of its dynamic capabilities. You don’t need a planner, you need a query compiler (in that it’s one and done, and you can even allow the thing the luxury of having actual time to optimize)
For proper data warehouses with multiple applications talking to it, planning is probably more useful than not. For the common modern situation with small/medium sized applications with a 1:1 relationship to their database, I’ve found it fairly rare that my data distribution changes significantly over time — and where it does, a lot more work needs to happen around it anyways.
Hints are the effective solution but they’re opt-in, weird non-standard extensions to the language and intrinsically tied to the planning engine; the big issue though is that they mainly exist to coerce/override the heuristics, which mainly fall over because planners are built to re-execute on every query with no real time to optimize/explore properly (you’ll give a C++ codebase hours to explore, but the RDBMS is granted mere milliseconds — a great injustice)