In a recent episode of The Weekly Iteration (Docker), Joe makes a funny, yet critical remark on using MongoDB. I am curious: @jferris: What’s the story behind this and what are other people’s experiences of using MongoDB in production?
I strongly recommend that all projects start out using a database with a strict, normalized schema. Postgres is an excellent choice for almost any new project. It’s so unlikely that Postgres is a bad choice for new projects that I’d recommend using it unconditionally and adding another database if you’ve proven that Postgres is causing problems.
Every project has data with a schema. If you need to look for specific properties (like a user’s email or a project’s name), you have a schema. Using a schema makes it easier to validate, search, and manage that data. It also makes it easier to create a database that performs well in most circumstances without resorting to gymnastics like sharding or replication. When your database system understands your schema, it can do a lot of work for you, like efficient joins. Good systems like Postgres even understand your schema and data well enough that it will rewrite your queries for you to be more efficient.
SQL is a well-understood, well-supported language with a ton of tutorials, books, and Stack Overflow answers. If you know how to describe a SQL query, somebody has already written a Stack Overflow answer with your query in it for any major DBMS.
Postgres and other SQL stores have excellent production providers. The Heroku Postgres offering is terrific. It’s the least painful way to run a database in production, period.
Postgres has nifty features like transactions and row-level locking. You won’t miss these features during development. You’ll miss them the first time you see a state bug in production, and you’ll end up being forced to implement your own pessimistic locking system.
Staying within the Postgres world as long as possible has a number of benefits. Every database you depend on is a potential point of failure. Staying within Postgres means you have one world of transactions, consistency, database backups, and guarantees. Want staging to look like production? Copy your Postgres database. Want to make sure background jobs created during a transaction are cancelled? Don’t worry about it; if your jobs are persisted in Postgres, they roll back with the transaction.
Leave the safe and reliable world of ACID compliance with great caution. If you really need to, I recommend augmenting Postgres with Redis. It’s a very reliable, simple store that does a good job of everything Postgres has trouble with. High-concurrency updates, queues, and caches are well-understood problems in the Redis world.
I don’t like to write negative posts, so I’d rather not dig into what I don’t like about Mongodb. All I’ll say is this: I said a number of good things above about Postgres and Redis. None of the good things I mentioned about Postgres and Redis are true of Mongodb.
Thanks a lot for the instant and detailed response, Joe!