Your app is still basically doing the same three things it did 15 years ago: put data somewhere, get it back fast, and don't lie to yourself about what "correct" means. AI can write half your code now, sure. It still can't feel that full-body dread when you realize you skipped a transaction and just billed real customers off half-written rows. strongdm
"Database" also stopped meaning "one big box with a cylinder icon on the diagram." Now it's a stack: primary store, a couple of specialty stores, and a cache layer so the primary doesn't sound like a jet engine every time you run a dashboard. Pick a boring default and only bolt on more pieces when you hit actual pain. You'll sleep more and page your friends less. aws.amazon
By the end of this, you'll know which boring default to reach for on a normal SaaS app, and when you actually need something fancy.
Relational databases: you're buying a contract
Relational databases give you tables, rows, columns, and a schema. The schema isn't paperwork; it's the contract that says "this is what reality is supposed to look like." SQL is how you enforce it. strongdm
The useful parts are not glamorous, but they keep you out of the ditch:
- Transactions: either the whole change happens or none of it does.
- Constraints: they stop garbage data from sneaking in.
- Joins: you connect things without inventing your own half-broken linkage system at 3 p.m. on a deploy day.
I landed on a Database Administration Services team at Rackspace once and spent months getting drilled on normalization, query plans, and join mechanics. At the time it felt like academic hazing. Later, watching production graphs go vertical while a bad query locked a table, I realized they were handing me tools to keep systems honest when everything goes sideways.
MySQL: the stubborn workhorse
MySQL is everywhere. Hosting, docs, StackOverflow answers, old blog posts from 2011 that still fix your problem. It's solid for straightforward CRUD SaaS apps and read-heavy workloads like dashboards and content feeds. strongdm
The rough edges mostly come from history: weird defaults, some behavior that doesn't match what you'd expect, fewer nice features than Postgres in certain areas. For a small app, that rarely matters. Your real problems are missing indexes and "let's just SELECT * in a loop, what could go wrong?". aws.amazon
Postgres: my default button
Postgres is my default if I'm starting from zero. Strong SQL, good performance for complex queries, serious ACID guarantees, and useful data types and extensions. JSONB lets you keep some flexibility without giving up the relational spine. strongdm
Postgres also shows up all over LLM and AI apps now because of extensions like pgvector. That matters because you can keep one database, one backup story, and one set of operations instead of juggling three services for data that really wants to live together. Install an extension, create a vector column, index it, and suddenly you have vector search inside the same database that holds your users and invoices. instaclustr
SQL Server (MSSQL): pulled in by Microsoft gravity
SQL Server shines in shops that already live in .NET and Azure. The tooling is polished, and plenty of teams know T‑SQL inside and out. If you're surrounded by legacy systems built on SQL Server, fighting that gravity is often not worth it. aws.amazon
The tradeoff is cost and licensing complexity compared to Postgres or MySQL, especially once you leave the hobby tier and start needing serious instances. If your stack is already Microsoft-heavy though, SQL Server is usually the path of least resistance. aws.amazon
Quick relational pick
If you want a rule of thumb:
- Postgres for greenfield work.
- MySQL if your team already has muscle memory there.
- SQL Server if you're in .NET land or sitting on SQL Server already.
For your first 0–10k users, schema design and query discipline matter more than which logo shows up on the admin screen. strongdm
NoSQL document stores: JSON with opinions
Document stores (MongoDB being the loudest name) store JSON‑ish blobs in collections instead of rows in tables. The pitch is flexibility: documents in the same collection don't have to share the exact same shape. aws.amazon
That's actually useful when your data model changes every week and you don't feel like running migrations every time you tweak a field. It's also nice when your access pattern is "fetch by ID, maybe filter on a couple of properties," instead of heavy relational joins.
Tradeoffs you're signing up for:
- Joins are weaker or awkward to express.
- Cross-document consistency becomes your job instead of the database's. aws.amazon
- Queries can turn into nested JSON spelunking if you're not careful.
- "It scales" is not a real argument if you have twelve paying customers.
The common mistake: people pick Mongo because it feels modern, then slowly rebuild a relational model by hand, with none of the safety rails that a relational database would have given them for free.
Vector stores: searching "meaning," not rows
Vector search is for similarity, not exact matches. You embed text or images into long lists of numbers, store those as vectors, and ask "what's closest to this vector?" instead of "what equals this string?". instaclustr
Under the hood, most systems use approximate nearest neighbor indexes like HNSW or IVF. You give up perfect correctness in exchange for "fast and close enough," which is fine when you care about semantic similarity more than exact matches. dbi-services
Use cases show up quickly once you build anything around LLMs:
- RAG over docs and product catalogs. yugabyte
- Semantic search for support portals and knowledge bases. yugabyte
- "You might also like"‑style recommendations. yugabyte
Do you need a dedicated vector database on day one? Usually, no. If you're already on Postgres, pgvector is often enough for small and medium AI features. Install the extension, add a vector column, make an index, and now your embeddings live next to your normal rows instead of in a separate system with its own billing, its own SDK, and its own failure modes. pecollective
Dedicated vector databases (Pinecone, Weaviate, Qdrant, etc.) start to make sense when your dataset is huge, your latency budget is tight, or you have complex multi‑tenant isolation needs that don't fit comfortably in one relational cluster. pecollective
Caches: keep your primary from melting
Caching is just storing expensive results in fast storage, usually RAM, so you don't hammer your database for every single request. It's the thing that makes your app feel snappy instead of "loading…" every time someone reloads a page. redis
Redis is the usual default: key/value storage plus data structures, pub/sub, rate limiting, and simple queue patterns. Memcached is the simpler cousin: string-in, string-out caching and not much else. redis
Things that make sense to cache:
- Hot reads like dashboards and feature flags.
- Expensive queries with joins or aggregations.
- Sessions and rate limits; Redis is common for both. redis
The classic cache mistakes are boring and predictable:
- Stale data when you forget to invalidate.
- Cache stampedes when everything expires at once; add jitter or locks to spread out the reloads. redis
- Using the cache as a band‑aid instead of fixing your schema or queries.
A boring 2026 stack for small SaaS
If you want a sane default stack that keeps complexity low while still letting you build AI features:
- Postgres as your primary store for users, billing, and core entities. aws.amazon
- JSONB columns in Postgres for flexible blobs, or Mongo if you've truly got a document‑first workload. aws.amazon
- A
pgvectortable or columns for RAG and semantic search on top of that same Postgres instance. instaclustr - Redis in front of hot endpoints for caching, sessions, and rate limiting. redis
AI can help you write migrations and queries, and it can definitely suggest indexes. It will not pick a consistency model for you or warn you that your "simple" partial update path can create ghost invoices in production.
The unglamorous stuff (tests, backups, logging, constraints) buys you the right to make decisions with incomplete information and still recover when you guess wrong. The real job is making sure tomorrow-you can clean up whatever today-you screwed up. strongdm
Tomorrow can deal with tomorrow. Just give it a database that didn't lie.
‑Sethers