Your Sunday, upgraded. Free live AI class · 5 PM ISTReserve your seat
APIS & BACKEND

Structure a Node.js App by Feature, Not by File Type

Folders named controllers, models and services scatter one feature across the codebase. Grouping code by feature keeps related files together and makes changes easier to find and review.

On this page

The core idea

Many Node.js projects start with folders by technical layer: routes, controllers, services, models. As features grow, changing one feature means editing files in four distant folders, and nobody can see a feature's full shape in one place. Organising by feature, such as courses, enrolments and payments, puts each feature's routes, logic, data access and tests together. Shared infrastructure, like database connection or logging, lives in a separate shared area. Layers still exist inside each feature; they are simply co-located.

A practical approach

Step 1

Identify the main features or domains of the application.

Step 2

Create a folder per feature containing its routes, service logic, data access and tests.

Step 3

Keep a shared folder for cross-cutting infrastructure: configuration, database client, logging and error handling.

Step 4

Let features communicate through exported functions from each feature's public entry file, not by importing each other's internal files.

Step 5

Move one feature at a time, running tests after each move, rather than reorganising everything at once.

Worked example

Adding a refund rule to an Express app requires changes in routes/payments.js, controllers/paymentController.js, services/paymentService.js and models/payment.js, plus tests in a separate tree. After moving to src/payments/ with routes, service, repository and tests together, the same change touches one folder, and the pull request is much easier to review.

A mistake to avoid

Do not let feature folders import from each other's internal files freely. Without boundaries, a feature-based structure becomes a different kind of tangle. Expose a small public interface per feature.

Try it yourself

Draw your project's folders and mark which files change for one recent feature. If they are spread across several layer folders, move that one feature into its own folder and see whether the next change is easier.

Your implementation checklist

  • Code is grouped by feature
  • Each feature holds its routes, logic, data access and tests
  • Shared infrastructure lives separately
  • Features use each other's public interfaces only
  • Restructuring happens incrementally with tests

Share or cite this guide

Innovate with Ajay Editorial (2026-10-07). Structure a Node.js App by Feature, Not by File Type. https://innovatewithajay.com/blogs/structure-a-node-app-by-feature

Editorial approach, sources and corrections

YOUR NEXT CHAPTER

You have the curiosity.
Let’s turn it into capability.

Start with a practical workshop or bring a specific question to Ajay.

Chat with Ajay