The Backend Setup Every Developer Should Follow

Published: (March 3, 2026 at 07:27 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

Cover image for The Backend Setup Every Developer Should Follow

Introduction

Before you write your backend code, it is very important to have a clean and organized setup — one that helps you scale, debug, and collaborate better.

There are 6 major layers of it:

  • Routes
  • Controllers
  • Middleware
  • Services
  • Repository
  • Database

Routes – The Entry Points

Routes define which function should run when a specific request hits your server. They map HTTP methods and URLs to controllers.

router.post("/signup", userController.signup);
router.get("/profile", authMiddleware, userController.getProfile);

Routes should be thin and clean. They don’t contain logic; they only decide where the request goes. Think of routes as the roadmap of your backend.

Controllers – The Request Handlers

Controllers handle:

  • Reading request data (req.body, req.params, req.query)
  • Sending response (res.json, res.status)
  • Calling the service layer

They should NOT:

  • Contain business logic
  • Talk directly to the database
  • Hash passwords
  • Calculate business rules

Think of controllers as the receptionist: they receive and respond.

Middleware – The Gatekeepers

Middleware runs before the controller. It is used for:

  • Authentication (JWT verification)
  • Logging
  • Input validation
  • Rate limiting
  • Error handling
router.get("/profile", authMiddleware, userController.getProfile);

The request must pass through middleware before reaching the controller. Think of middleware as the security check at the airport.

Services – The Brain of the Application

This is where your real logic lives. Services handle:

  • Business rules
  • Data transformations
  • Workflow decisions
  • Orchestration of multiple repositories
exports.signup = async ({ email, password }) => {
  const existingUser = await userRepository.findByEmail(email);

  if (existingUser) {
    throw new Error("User already exists");
  }

  const hashedPassword = await bcrypt.hash(password, 10);

  return await userRepository.createUser(email, hashedPassword);
};

Think of services as the decision‑maker.

Repository – The Data Access Layer

The repository is responsible for:

  • Communicating with the database
  • Executing queries
  • Returning raw data

It does NOT:

  • Decide business rules
  • Validate logic
exports.findByEmail = async (email) => {
  return db("users").where({ email }).first();
};

Repository is an abstraction over the database. If you switch from PostgreSQL to MongoDB, only the repository layer should change. Think of the repository as the translator between your app and the database.

Database – The Storage Engine

This is your:

  • PostgreSQL
  • MySQL
  • MongoDB
  • Supabase

Its job is simple:

  • Store data
  • Retrieve data
  • Maintain integrity

It does not care about HTTP, business logic, or application rules; it only stores information.

Full Request Flow

  1. A user signs up.
  2. Request hits Route.
  3. Middleware validates token/input.
  4. Controller receives request.
  5. Controller calls Service.
  6. Service applies business logic.
  7. Service calls Repository.
  8. Repository talks to Database.
  9. Response travels back up the chain.
Database → Repository → Service → Controller → Client

Clean. Predictable. Scalable.

🧠 Simple Mental Model

If you’re ever confused where something belongs, ask:

  • Does it handle HTTP? → Controller
  • Does it validate/authenticate/log? → Middleware
  • Is it business logic? → Service
  • Is it a database query? → Repository
  • Is it storage? → Database
  • Does it map endpoint to controller? → Route

This structure is inspired by architectural principles popularized in Clean Architecture by Robert C. Martin — but simplified for practical backend applications.

0 views
Back to Blog

Related posts

Read more »

Stop Building API Dashboards From Scratch

Every API developer has been there. You ship an API, someone starts using it, and the questions begin: - “How many requests are we getting?” - “Who’s our heavie...

The Importance of TDD

The Problem I built an “awesome” API with 12 parameters. It was garbage. Nobody could use it without a PhD in my brain. After years of backend development, I l...