The pipeline: validate → authenticate → handle
When a request reaches your API, order matters. A robust handler always processes it in three steps, and stops as soon as something fails:
- Validate the input. Are the required fields present? If not, respond 400 Bad Request and stop. There's no point continuing with incomplete data.
- Authenticate the caller. Do they bring valid credentials (an authorization header, a token)? If not, respond 401 Unauthorized and stop.
- Handle the action: now with good data and a known user, run the logic (read/create/update) and respond with success, e.g. 201 Created.
function handleRequest(req, res, deps) {
// 1. validate -> 400 if something is missing
// 2. authenticate -> 401 if there are no credentials
// 3. handle -> use deps to do the work and respond 201
}
Notice that we validate before authenticating: rejecting malformed input is
cheap and reveals nothing. The dependencies (the database, the repo) are
injected by parameter (deps): this way the handler is easy to test with
mocks and isn't tied to a concrete implementation.
Production checklist
"It works on my machine" isn't being ready. Before opening your SaaS to the public, go through a minimal, non-negotiable list:
- tests: the suite passes green.
- secrets: keys and passwords out of the code, in environment variables.
- https: traffic encrypted end to end.
- logging: records to know what happened when something fails.
- backups: data backups, tested.
- monitoring: alerts that warn before the customer notices.
If anything on that list is missing, you don't launch. You'll build a
function that takes the state of each item and says whether you're ready and
what's missing. And, since each environment needs different settings (a local DB
in dev, a managed one in prod), you'll add a loadConfig(env) that
applies default values.