Express JS Basics
Interview Questions with Answers

1. What is Express.js, and why is it popular with Node.js?

Express.js is a lightweight and flexible web application framework built on top of Node.js. It simplifies the process of handling HTTP requests, routing, middleware, and server logic. In raw Node.js, developers have to manually handle request URLs, headers, and responses — Express automates much of this by offering easy-to-use methods like app.get() and app.post().
It became popular because it is unopinionated (you can structure your app your own way), integrates seamlessly with Node’s event-driven nature, supports middleware (for modular and reusable code), and has a vast ecosystem of extensions for authentication, databases, and security.

2. What is the default port usually used in Express apps?

By convention, developers use port 3000 when running local Express applications. It’s not mandatory, but it became a community standard. You can, however, use any available port number if 3000 is already occupied.

Boost your Express JS skills and get interview-ready today!

3. How do you install Express in a Node.js project?

To install Express, you first initialize a Node.js project using:

npm init -y

Then, you install Express with:

npm install express

This command adds Express to your project’s dependencies and allows you to import and use it within your JavaScript files.

4. How do you create a basic Express.js application?

A simple Express application is created by importing Express, creating an app instance, defining routes, and starting a server:

const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Welcome to Express!');
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});

Here, app.get() defines a route for GET requests to the root URL, and app.listen() starts the server on port 3000.

What is the purpose of app.get() in Express?

app.get() is used to define a route that listens for HTTP GET requests at a specified URL path. When a client (such as a browser) sends a GET request to that path, the provided callback function executes and sends a response.

Example:

app.get('/home', (req, res) => {
res.send('This is the home page');
});

This is primarily used to fetch or display data, not to modify it.

6. What is routing in Express?

Routing in Express refers to defining how your application responds to different client requests (GET, POST, PUT, DELETE, etc.) made to various URLs. Each route specifies a path and an HTTP method, along with a callback function that determines what the server should send back.
Routing forms the backbone of any web application because it controls how URLs map to functionality.

7. How do you define a simple route for the home page (/)?

You can define a home page route using the app.get() method:

app.get('/', (req, res) => {
res.send('Welcome to the Home Page');
});

This route listens for GET requests at / and sends the specified message as a response.

8. What is the difference between app.get() and app.post()?

app.get() handles GET requests, which are used to retrieve data from the server. These requests do not modify server data and usually carry parameters in the URL.
app.post() handles POST requests, which are used to send data to the server (for example, from a form or API client). POST requests usually include data in the body of the request rather than the URL.

In short, GET is for reading, and POST is for creating or submitting data.

9. How do you handle route parameters in Express?

Route parameters are variables in the URL path, defined by a colon (:). They are accessed via req.params.
Example:

app.get('/users/:id', (req, res) => {
const userId = req.params.id;
res.send(`User ID: ${userId}`);
});

If a client requests /users/45, the response will display “User ID: 45”.

10. How do you handle query parameters in Express?

Query parameters appear after a question mark (?) in the URL and are accessed using req.query.
Example:

app.get('/search', (req, res) => {
const keyword = req.query.q;
const limit = req.query.limit;
res.send(`Search for: ${keyword}, Limit: ${limit}`);
});

If a client requests /search?q=node&limit=5, the response will be “Search for: node, Limit: 5”.

11. What is middleware in Express?

Middleware functions are functions that run between receiving a request and sending a response. They can modify the request or response objects, perform validation, authentication, logging, or error handling, and then either end the request or call next() to pass control to the next middleware or route handler.

Express itself is built around this middleware concept.

12. How do you define a middleware function in Express?

A middleware function accepts three parameters: req, res, and next.

Example:

function logger(req, res, next) {
console.log(`${req.method} ${req.url}`);
next(); // Move to the next middleware or route
}
app.use(logger);

Here, the logger middleware logs all incoming requests before passing control onward.

13. What is the purpose of next() in middleware?

The next() function tells Express to move on to the next middleware or route handler in the stack. If it’s not called, the request will stop in the current middleware, causing the application to hang because no response will be sent.

14. How do you use built-in middleware in Express?

Express comes with several built-in middleware functions:

  • express.json() — Parses incoming JSON request bodies.
  • express.urlencoded() — Parses URL-encoded data (for form submissions).
  • express.static() — Serves static files such as images, CSS, or JS files.

Example:

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static('public'));

15. What is the difference between application-level and router-level middleware?

Application-level middleware is applied directly to the app object using app.use() and affects all routes or specific paths.

Router-level middleware, on the other hand, is applied to an instance of express.Router() and only affects routes within that router.

Router-level middleware helps organize routes into modules, making the app more maintainable in large projects.

16. How do you access request parameters in Express?

You can access different types of parameters using:

  • req.params for route parameters (/users/:id)
  • req.query for query strings (?page=2)
  • req.body for POST data (requires body parser)
  • req.headers for HTTP headers

Example:

app.post('/user/:id', (req, res) => {
const id = req.params.id;
const name = req.body.name;
res.send(`User ${id} is ${name}`);
});

17. How do you send a JSON response in Express?

To send JSON data, use res.json():

app.get('/info', (req, res) => {
res.json({ course: 'Node.js', duration: '6 months' });
});

This automatically sets the appropriate headers and converts the object into a JSON string.

18. How do you set a response status code in Express?

You can specify a status code before sending a response using res.status():

res.status(404).send('Page not found');

or

res.status(201).json({ message: 'Created successfully' });

It allows the server to communicate success, error, or redirection codes clearly to clients.

19. How do you redirect a user to another route in Express?

You can use the res.redirect() method:

res.redirect('/login');

By default, it uses a 302 status code (temporary redirect). You can also specify a code:

res.redirect(301, '/new-location');

20. How do you send static files in an Express application?

Static files like images, CSS, and JavaScript are served using the built-in express.static() middleware.
Example:

app.use(express.static('public'));

This allows clients to access any file placed in the “public” directory directly through the browser, such as http://localhost:3000/logo.png.

Don’t just learn — master Express JS and land your dream job!

21. What is the purpose of express.json() middleware?

It parses incoming requests with a Content-Type: application/json body and populates the parsed object on req.body. Without it, req.body would be undefined for JSON payloads. You can tune size and parsing behavior with options like limit, strict, and reviver.

app.use(express.json({ limit: '1mb', strict: true }));
app.post('/api/users', (req, res) => {
// req.body is a JS object parsed from JSON
res.json({ received: req.body });
});

22. What is the purpose of express.urlencoded() middleware?

It parses URL-encoded form submissions (e.g., from HTML <form method=”post”>) and puts the result on req.body. The extended option controls which parser is used.

  • extended: false uses the Node.js querystring parser (simple key–value).
  • extended: true uses qs (supports nested objects and arrays).
app.use(express.urlencoded({ extended: true }));
app.post('/submit', (req, res) => {
// e.g., name=Ana&tags=js&tags=node -> { name: 'Ana', tags: ['js','node'] }
res.json(req.body);
});

23. How do you serve static files with express.static()?

Mount the static middleware pointing to a directory. Express maps file paths under that directory to URLs.

app.use(express.static('public'));           // GET /logo.png -> public/logo.png
app.use('/assets', express.static('public')); // GET /assets/app.css -> public/app.css

For caching, set response headers via a small wrapper or reverse proxy (see Q24).

24. How do you set response headers in Express?

Use res.set() (alias res.header()) to set one or multiple headers before sending the body.

app.get('/report', (req, res) => {
res
   .set('Cache-Control', 'no-store')
   .set('X-Frame-Options', 'DENY')
   .type('application/json')
   .status(200)
   .send(JSON.stringify({ ok: true }));
});

For headers applied to many routes, use middleware:

app.use((req, res, next) => {
res.set('X-Powered-By', 'none');
next();
});

25. How do you handle file downloads in Express?

Use res.download() to set proper headers and stream a file as an attachment, or res.attachment() plus res.sendFile() for finer control.

const path = require('path');
app.get('/download/invoice', (req, res, next) => {
const filePath = path.join(__dirname, 'files', 'invoice.pdf');
res.download(filePath, 'Invoice-2025.pdf', err => {
   if (err) next(err);
});
});

res.download() automatically sets Content-Disposition: attachment; filename=… and streams efficiently.

26. What is express.Router() used for?

It creates a mini, modular router instance that you can attach routes and middleware to. This lets you group related endpoints and mount them under a path, improving structure, testability, and maintainability in larger apps.

27. How do you create modular route files with express.Router()?

Create a file per resource, build routes on a Router, export it, and mount in your main app.

// routes/users.js
const { Router } = require('express');
const router = Router();
router.get('/', (req, res) => res.json([{ id: 1, name: 'Ana' }]));
router.post('/', (req, res) => res.status(201).json(req.body));
module.exports = router;
// app.js
const usersRouter = require('./routes/users');
app.use('/users', usersRouter);

28. How do you mount a router on a path in Express?

Use app.use(<basePath>, <router>). All routes defined in the router are now reachable under that base path.

app.use('/api/v1/users', usersRouter);

29. Can you apply middleware only to a specific router?

Yes. Use router.use(mw) to attach middleware that runs only for routes inside that router, or pass middleware to specific routes.

const { Router } = require('express');
const router = Router();
function auth(req, res, next) { /* check token */ next(); }
router.use(auth);                // applies to all routes below
router.get('/me', (req, res) => res.json({ me: true }));
module.exports = router;

30. How do you organize routes in a large Express app?

Split by domain/resource using routers, keep controllers/services separate from routing, centralize error handling and validation, and use a layered directory structure. One common pattern:

src/
app.js
routes/
   users.routes.js
   auth.routes.js
   products.routes.js
controllers/
   users.controller.js
   auth.controller.js
services/
   users.service.js
middlewares/
   auth.js
   error.js
   validate.js
validations/
   users.schema.js
utils/
    logger.js

Routers should be thin: only route definitions and wiring. Business logic lives in controllers/services. Validation and auth are reusable middlewares.

31. How do you parse JSON data from a request body?

Enable express.json() before your routes and access req.body.

app.use(express.json());
app.post('/api/items', (req, res) => {
// e.g., { "name": "Pen", "price": 10 }
res.status(201).json({ saved: req.body });
});

32. How do you parse URL-encoded form data in Express?

Use express.urlencoded({ extended: true }) and read req.body.

app.use(express.urlencoded({ extended: true }));
app.post('/signup', (req, res) => {
const { username, password } = req.body;
res.json({ username });
});

33. How do you handle form submissions in Express?

Enable parsing middleware, then read fields from req.body. For file uploads, add Multer (see Q34).

app.use(express.urlencoded({ extended: true }));
app.post('/contact', (req, res) => {
const { name, email, message } = req.body;
// save or process
res.status(200).send('Thanks, we received your message.');
});

34. How do you handle file uploads with Express and Multer?

Install Multer, configure storage (memory or disk), and attach it to routes. Then access uploaded files on req.file or req.files.

// npm i multer
const multer = require('multer');
const upload = multer({ dest: 'uploads/' }); // disk; or multer({ storage: multer.memoryStorage() })
app.post('/avatar', upload.single('avatar'), (req, res) => {
// req.file: { fieldname, originalname, mimetype, path, size, ... }
res.json({ stored: req.file.originalname, path: req.file.path });
});
// For multiple files:
// app.post('/photos', upload.array('photos', 5), (req, res) => res.json({ count: req.files.length }));

Always validate file type/size and consider scanning and access-control. For cloud storage, stream to S3, GCS, etc., rather than keeping large files on your server.

35. How do you validate user input in Express?

Use a validation library and a small wrapper middleware. Popular choices are joi, zod, or express-validator.

Example with zod:

// npm i zod
const { z } = require('zod');
const userSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().min(0).optional()
});
function validate(schema) {
return (req, res, next) => {
   const result = schema.safeParse(req.body);
   if (!result.success) {
     return res.status(400).json({ errors: result.error.issues });
   }
   req.validated = result.data;
   next();
};
}
app.post('/users', express.json(), validate(userSchema), (req, res) => {
res.status(201).json({ user: req.validated });
});

This keeps controllers clean and prevents bad data from reaching your logic or database.

36. How do you handle errors in Express routes?

Wrap async logic and pass errors to Express’s error pipeline using next(err), or rely on a small async helper. Then centralize responses in an error-handling middleware.

// helper
const asyncH = fn => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
app.get('/may-fail', asyncH(async (req, res) => {
// if something throws, asyncH sends it to next(err)
const data = await riskyCall();
res.json(data);
}));

37. What is the role of the error-handling middleware in Express?

It is a special middleware with the signature (err, req, res, next) that handles all errors forwarded via next(err) or thrown in async handlers. Put it after all routes to send consistent error responses and hide stack traces in production.

app.use((err, req, res, next) => {
const status = err.status || 500;
const msg = process.env.NODE_ENV === 'production' ? 'Internal Server Error' : err.message;
res.status(status).json({ error: msg });
});

38. How do you return a 404 response in Express?

Add a “not found” handler after all defined routes. If no route matched, this middleware runs.

app.use((req, res) => {
res.status(404).json({ error: 'Not Found' });
});

39. How do you handle invalid JSON payloads in Express?

express.json() throws a SyntaxError for malformed JSON. Write an error handler that checks for this case and returns 400 Bad Request.

app.use(express.json());
app.use((err, req, res, next) => {
if (err instanceof SyntaxError && 'body' in err) {
   return res.status(400).json({ error: 'Invalid JSON' });
}
next(err);
});

Place this before your general error handler (or handle both in one, checking the error type).

40. How do you log errors in an Express application?

Use an error-logging middleware or a logger library (e.g., winston, pino) inside the error handler, including request metadata for traceability.

const pino = require('pino');
const logger = pino();
app.use((err, req, res, next) => {
logger.error({
   msg: err.message,
   stack: err.stack,
   method: req.method,
   url: req.originalUrl,
   ip: req.ip
});
res.status(500).json({ error: 'Internal Server Error' });
});

For production, prefer structured JSON logs, avoid leaking internals to clients, and ship logs to a central system (e.g., CloudWatch, ELK, Loki) with correlation IDs.

Take the next step in your web development journey now!

41. What is the purpose of cookies in an Express app?

Cookies are small key–value strings the server asks the browser to store and send back with future requests. They’re used to persist lightweight data across requests, such as a session ID, UI preferences, A/B bucket, or a short-lived token. Because cookies travel with every request to their domain and path, keep them small and avoid sensitive data unless they’re secured (Secure, HttpOnly, SameSite, limited maxAge).

42. How do you set a cookie in Express?

Use res.cookie(name, value, options) before sending the response.

app.get('/login', (req, res) => {
res.cookie('sid', 'abc123', {
   httpOnly: true,
   secure: true,        // use HTTPS in production
   sameSite: 'lax',
   maxAge: 1000 * 60 * 60 // 1 hour
});
res.send('Logged in');
});

43. How do you read cookies in an Express application?

Install and use cookie-parser, then read req.cookies (and req.signedCookies if signing).

// npm i cookie-parser
const cookieParser = require('cookie-parser');
app.use(cookieParser('your-signing-secret'));
app.get('/me', (req, res) => {
const sid = req.cookies.sid;           // unsigned
// const sid = req.signedCookies.sid;  // if set with signed: true
res.json({ sid });
});

44. What is the purpose of sessions in Express?

Sessions let you associate server-side state with a client across requests. Instead of storing user data in a cookie, you store only a session ID in the cookie, and keep the actual data on the server (or a shared store like Redis). This enables authentication, carts, and multi-step flows while keeping cookies small and more secure.

45. How do you install and use express-session middleware?

Install it, configure a secret, and choose a store for production (Redis, database). By default it uses an in-memory store, which is not suitable for production.

// npm i express-session
const session = require('express-session');
app.set('trust proxy', 1); // if behind a proxy (Heroku/NGINX)
app.use(session({
name: 'sid',
secret: 'replace-with-strong-secret',
resave: false,
saveUninitialized: false,
cookie: {
   httpOnly: true,
   sameSite: 'lax',
   secure: process.env.NODE_ENV === 'production',
   maxAge: 1000 * 60 * 60
}
}));
app.get('/set', (req, res) => {
req.session.user = { id: 1, role: 'admin' };
res.send('session set');
});
app.get('/get', (req, res) => {
res.json(req.session.user ?? null);
});

46. How do you build a simple REST API with Express?

Create an app, use JSON parsing, and define CRUD endpoints that return JSON and appropriate status codes.

const express = require('express');
const app = express();
app.use(express.json());
let items = [{ id: 1, name: 'Pen' }];
app.get('/api/items', (req, res) => res.json(items));
app.get('/api/items/:id', (req, res) => {
const item = items.find(i => i.id === Number(req.params.id));
return item ? res.json(item) : res.status(404).json({ error: 'Not found' });
});
app.post('/api/items', (req, res) => {
const it = { id: Date.now(), ...req.body };
items.push(it);
res.status(201).json(it);
});
app.listen(3000);

47. How do you return JSON data from an API endpoint in Express?

Use res.json(object). It sets the Content-Type: application/json header and stringifies for you.

app.get('/api/status', (req, res) => res.json({ ok: true, time: Date.now() }));

48. What is the difference between GET and POST in an API?

GET is for retrieving data and should be safe and idempotent; parameters usually come via path or query string, and bodies are generally not used. POST is for creating or submitting data; it carries a request body, is not idempotent, and often returns 201 Created with a representation of the new resource or its location.

49. How do you test an Express API using Postman?

Run your server, open Postman, create requests to your endpoints, set method and URL, add query params or a JSON body, and send. Check the response status, headers, and body. You can also save collections, add environment variables, write tests (PM scripts), and chain requests to automate regression checks.

50. How do you handle cross-origin requests in Express?

Enable CORS by sending the proper headers. The easiest path is the cors middleware.

// npm i cors
const cors = require('cors');
app.use(cors({ origin: ['https://your-frontend.com'], credentials: true }));

For credentials with cookies/sessions, also set credentials: true, ensure the browser request has withCredentials: true, and avoid * as origin—use an explicit origin.

51. What is the purpose of package.json in an Express app?

It declares your app’s metadata, scripts, dependencies, engines, and more. Node and npm use it to install modules, run scripts like npm start, and lock dependency ranges. It’s also where you declare the main entry and Node version constraints for deployment.

52. How do you run an Express app with nodemon?

Install nodemon as a dev dependency

npm i -D nodemon

and add a dev script.

// package.json
{
"scripts": {
   "dev": "nodemon src/server.js",
   "start": "node src/server.js"
}
}

Then run npm run dev to auto-restart on file changes.

53. What is the difference between development and production modes in Express?

Development mode favors fast feedback and verbosity: detailed error messages, relaxed caching, maybe extra logs and hot reload. Production mode emphasizes security, performance, and stability: minified assets, strict CORS, secure cookies, trust proxy, Helmet, rate limiting, robust logging, and hiding stack traces from clients. Typically you toggle behavior via process.env.NODE_ENV.

54. How do you set environment variables in an Express app?

Set them in your shell or a .env file and read via process.env.

With dotenv:

npm i dotenv

Code:

require('dotenv').config(); // early in your entry file
const port = process.env.PORT || 3000;
app.listen(port);

In production platforms, set env vars in the provider’s configuration panel or CLI.

55. How do you organize an Express project into routes, controllers, and models?

Use a layered structure: routers define URL→controller mappings; controllers handle HTTP concerns; services contain business logic; models or ORMs handle persistence. For example:

src/
server.js
routes/
   users.routes.js
controllers/
   users.controller.js
services/
   users.service.js
models/
   user.model.js
middlewares/
   auth.js
   validate.js
utils/
    logger.js

Routers stay thin; controllers validate and shape responses; services do the work; models interact with the DB. This separation makes testing and scaling easier.

56. What types of applications can you build with Express.js?

REST and GraphQL APIs, SSR web apps, microservices, real-time backends (with Socket.IO), admin dashboards, webhooks processors, BFF (Backend-for-Frontend) layers for SPAs/mobile apps, and small utilities like proxy servers or cron-triggered workers.

57. Why is Express called “unopinionated”?

Express gives you primitives—routing, middleware, req/res helpers—without enforcing folder structures, ORMs, templating engines, or state management choices. You decide your architecture, libraries, and conventions, which is powerful for experienced teams and flexible for varied use cases.

58. How do you connect an Express.js app to a MongoDB database?

To store and retrieve data in a persistent way, Express applications often connect to MongoDB using the official Mongoose ODM. Mongoose provides a schema-based layer on top of MongoDB and makes interaction with collections cleaner and safer.

Install Mongoose:

npm install mongoose

Import and connect: In your main server file (for example app.js or server.js):

const express = require('express');
const mongoose = require('mongoose');
const app = express();
mongoose.connect('mongodb://127.0.0.1:27017/studentdb', {
   useNewUrlParser: true,
   useUnifiedTopology: true
})
.then(() => console.log('MongoDB Connected'))
.catch(err => console.error('MongoDB connection error:', err));
app.use(express.json());
app.listen(3000, () => console.log('Server running on port 3000'));

Create a model (schema):

const studentSchema = new mongoose.Schema({
name: String,
email: String,
course: String
});
const Student = mongoose.model('Student', studentSchema);

Use it in a route:

app.post('/students', async (req, res) => {
const student = new Student(req.body);
const saved = await student.save();
res.status(201).json(saved);
});

59. How do you add third-party middleware to an Express project?

Install the package, require it, and plug it into the middleware chain with app.use() or on specific routes.

// CORS
const cors = require('cors');
app.use(cors());
// Security headers
const helmet = require('helmet');
app.use(helmet());
// Rate limiting
const rateLimit = require('express-rate-limit');
app.use(rateLimit({ windowMs: 15*60*1000, max: 100 }));

Always read docs for order dependencies (e.g., session before passport).

60. What are the main advantages of using Express over plain Node.js HTTP?

Cleaner routing and middleware composition, built-in body parsing and response helpers, huge ecosystem of plugins, clearer separation of concerns, faster development, and less boilerplate. You can still drop down to the raw http layer if needed, but Express covers 90% of web-app needs with far fewer lines of code.

Note: The interview questions and answers provided on this page have been thoughtfully compiled by our academic team. However, as the content is manually created, there may be occasional errors or omissions. If you have any questions or identify any inaccuracies, please contact us at team@learn2earnlabs.com. We appreciate your feedback and strive for continuous improvement.