A MongoDB Atlas REST API with no backend to write

CRUD, bcrypt-hashed passwords and real aggregation pipelines over an Atlas cluster — from config. No ORM, no Mongoose, no server to deploy.

Step 1 — The Atlas cluster

If you already have one, skip to step 2. Otherwise:

Step 2 — One managed variable

| Name | Value | |---|---| | MONGODB_URI | the SRV string from step 1 |

Step 3 — Your first endpoint

Declare the database once, then each interface is a route:

Step 4 — Writes, with validation that documents itself

Those assert tests aren't only guards — they generate the OpenAPI request body. The description: on each becomes the field description in the published schema, so the docs stay correct because they're the same declaration that does the validating. There's no second place to update.

Step 5 — Passwords, done properly

This is where hand-rolled tutorials usually hand-wave. Hashing happens as a transform between validation and insert:

Step 6 — Aggregation, which is the actual reason to use Mongo

Everything so far is CRUD, and CRUD looks the same on any database. This part doesn't.

Step 7 — Locking it down

Air Pipe validates JWTs; it doesn't mint them. Your app already issues tokens, so validation is the first action and everything else waits on it:

What comes with it

From the same files, no extra work: an OpenAPI document generated from the assert tests and response_example blocks, Prometheus metrics per route, and an OpenTelemetry trace per request showing each action and how long the Mongo call took. When an aggregation gets slow, the trace tells you whether it's the pipeline or the network before you start guessing.

The shortcut

All of it ships as one pack — users, posts and categories CRUD, the four aggregation endpoints, the JWT pattern, and a seed endpoint that loads sample data so the analytics have something to chew on. Set MONGODB_URI, deploy, call /api/seed.

Things that will bite you

$set overwrites. MongoDB update semantics replace the fields you send rather than merging, so the update endpoints require the full set of fields you want changed. There's no COALESCE-style partial update. No reference integrity. A post's author and category are plain strings; Mongo won't check they point at a real user or category. That's the trade for schema flexibility, and keeping them consistent is your application's job. Human keys, not ObjectIds. Lookups use username and slug rather than _id, which keeps URLs readable and avoids ObjectId casting on every request. Both need a unique index in Atlas — add one, because nothing else will stop a duplicate.

Related packs