database · tutorial · comparison

Mongo Today, Postgres Tomorrow? Read This First

Mongoose schemas, index discipline, and the parity verbs that keep Mongo portable. Use documents well, escape cleanly. Inside.

Harry Houdini in handcuffs and leg irons, hands raised, in front of a wooden crate and a crowd, New York Harbor, 1912
Harry Houdini in handcuffs and leg irons, hands raised, in front of a wooden crate and a crowd, New York Harbor, 1912 · Photo: Bain News Service, public domain, via Wikimedia Commons

Documents became a swamp

Picture year one with Mongo.

No migrations.

Nested orders inside users.

Ship daily.

Year two, the swamp.

User documents with eleven optional fields, three deprecated, nobody sure.

Orders nested three levels deep and unqueryable for analytics.

Two collections holding the same email in different shapes.

Queries turn into archaeology. Which of the four email fields is canonical? Aggregations that SQL does in one line become pipeline stages written once and feared forever.

The flexibility you loved early becomes ambiguity you pay for monthly.

Teach documents with discipline. And leave the exit open.

Disciplined or swamp

Practice Swamp, year two Disciplined
Schema Schemaless, "flexible!" Real schemas, required fields
Email fields Several variants, unknown canon One, unique and indexed
Nesting Orders three deep in users References and plain reads
Indexes Whatever defaulted Declared per query pattern
Portability Locked to aggregations Shared actions mirror SQL

The swamp teaches three lessons.

Schemaless means schema-later, with interest. Every unspecified field becomes a migration question under deadline instead of at design. Schemas with required flags and defaults cost minutes up front and save quarters of archaeology.

Nesting optimizes reads and bankrupts everything else. Embedded orders load fast and analyze never. Reference by ID. Read plain data. Join in code at solo scale.

Aggregations are lock-in wearing power. A lookup labyrinth translates to no SQL engine. Shared actions keep cleverness portable: implement per engine, call uniformly.

What to do

Schema everything. Require deliberately.

Each entity gets a real schema with required fields and defaults, mirroring the columns on the other engines. A user is an email, a paid-access flag and a plan type, with the same meanings everywhere.

Schemas are documentation the database enforces. They stop the swamp at the front door.

Index per query pattern. Check with explain.

Every list the app shows needs a supporting index, declared beside the schema and reviewed with it.

Unindexed MongoDB at scale is a full-collection scan wearing a query costume. Silent at a thousand documents. Fatal at a million.

Every so often, run explain on your busiest queries and confirm they use an index.

Speak through the shared actions. Never Mongoose directly.

The app asks for "this user's orders" through one set of actions. Underneath, MongoDB returns plain objects instead of heavy document instances.

The rest of the app is engine-blind. The day another database calls, those actions get a new implementation and no feature code changes.

Swamp or disciplined

Audit question Swamp era Disciplined
Which email field is canonical? Nobody is sure One, unique and indexed
Analytics queries Pipeline archaeology Plain finds, joins in code
Slow-query risk Found in production Declared and checked
Switching to Postgres A rewrite of every aggregation Reimplement the shared actions
A new developer "Ask someone" "Read the schemas"

The cost

Discipline costs upfront thought per field.

Required?

Default?

Index?

That is minutes per schema, paid before any pain. Against swamp quarters, it is afternoons against months.

Know this first

MongoDB is not the default. SQLite is simpler and free for a single box.

Choose MongoDB for document-shaped data or an existing team.

Why BoringPush is the way to do this

MongoDB, with a way out.

BoringPush gives MongoDB real schemas and the same behavior as SQLite and Supabase. Your app code never knows which one runs.

Stay as long as it fits.

FAQ

Is MongoDB better than SQLite-first for most solos?

Rarely at the start. SQLite wins on zero setup, file speed and trivial backups at single-box scale.

MongoDB earns its place with document-shaped data such as nested configs and variable attributes, or when a team already knows it. Default to SQLite, choose MongoDB for shape-fit, and keep parity either way.

How do transactions work across engines?

Each engine has its own. MongoDB supports multi-document transactions on a replica set, SQLite has its own transaction modes and Postgres has the usual ones.

Keep cross-entity writes rare by design, and transact where atomicity truly matters. The shared actions cover the verbs, while transactions stay engine-native.

Should I use Mongoose or the native driver?

Mongoose for solos, because schemas enforce discipline. The kit standardizes on Mongoose with plain-object reads. Keep virtuals and deep populate chains minimal, because magic you cannot trace is magic you will debug at midnight.

How do I migrate messy data into disciplined schemas?

Freeze writes to the ambiguous fields, export and profile them, and write transforms that pick a canonical value. Import behind schema validation and verify counts. Do one collection at a time, on staging first, with snapshots taken beforehand.

Do text search and analytics belong in MongoDB?

Basic text indexes cover simple search such as product names and post titles. Serious search graduates to a dedicated engine later.

Analytics can read plain results into code at solo scale. Move to pipelines or a warehouse when you outgrow that, on evidence.

When is MongoDB the wrong call?

For relational-heavy domains such as ledgers, complex joins and strict integrity across entities, where SQL's guarantees do real work daily. Match the engine to your integrity needs first, and fashion never.

Keep reading

+ all the boring stuff (analytics, auth, SQLite ↔ Supabase, full marketplace, webhooks)

The Agent-First Shipping Kit

Command from your phone.

Built so autonomous AI agents build what you want without breaking what's already paying you.

$199

Get BoringPush

One-time payment · Lifetime updates · Unlimited projects.

Keep reading