What Express is
http module.Asked in interviews
AskedWhat is Express.js and why is it used?req, res and next. It sends a response or calls next(). If it does neither, the request hangs.next(err) or a thrown error skips the normal functions and jumps to the error handler, the one with four parameters.http module.Asked in interviews
AskedWhat is Express.js and why is it used?npm install expressconst app = express();app.post('/users', fn);app.listen(3000); TrapA method no route handles, such as PATCH, gets 404.
:id from the URL pathreq.params.id?sort=name from the query stringreq.query.sortreq.body.name:id on every route that has itapp.param('id', fn);TrapAll three come from the client, so validate them. Every param is a string.
/*/*splat?/users{/:id}app.del() and res.send(status) app.delete()res.sendStatus() req.param() is gone, and req.query is read-only.TipA rejected promise now reaches the error handler, as long as the route returns or awaits it.
TrapString paths reject regular expressions, so :id(\d+) fails.
Asked in interviews
AskedWhat changed between Express 4 and Express 5?next()next(err)next('route')return next();TrapA middleware that neither responds nor calls next() hangs the request.
TipParsers and auth go first. The 404 and error handlers go last.
Asked in interviews
AskedWhat is Express.js middleware execution order?app.use('/api', fn);Mount middleware on a sectionapp.get('/api/users', fn);Answer GET and HEAD on one pathapp.all('/api/users', fn);Run a rule for every method on one pathTipPrefix means /api also matches /api/users. Strips means Express removes the mount path from req.url.
const router = express.Router(); app.use('/users', router);router.use(requireAuth); TipA router is a mini-application with its own middleware and routes, but no server.
Asked in interviews
AskedWhat is Express Router and why use it?req.body = fn(req.body);const orig = res.json;res.json = (d) => orig.call(res, fn(d));TrapCall the original with this set to res, or Express can't send the body.
Asked in interviews
AskedHow do you implement request/response transformation middleware?app.use((err, req, res, next) => {});if (res.headersSent) return next(err);Promise.resolve(fn(req, res, next)).catch(next); TipIn Express 4, a rejected promise goes unhandled and crashes the process by default since Node.js 15.
TrapExpress spots it by its four parameters, so keep next even when unused.
Asked in interviews
AskedHow do you implement error handling in Express.js?app.use((req, res) => res.sendStatus(404)); 404 from the route, or pass an error with that status.TrapA 404 isn't an error, so the error handler never sees it.
Asked in interviews
AskedHow do you handle 404 errors in Express.js?class AppError extends Error {}this.isOperational = true;500.TipAn operational error is an expected failure, such as a missing record. A programmer error is a bug.
res.send('<p>Hi</p>'); Send text or HTMLres.json(null);Send JSON, even nullres.status(204).end(); End with no body, using Node's own methodTipCall only one per request. The first call ends the response.
Asked in interviews
AskedWhat is the difference between res.send(), res.json() and res.end()?app.set('view engine', 'ejs');res.render('index', { title });app.locals.siteName = 'Acme';res.locals.user = req.user;TrapEvery request sees the same app.locals, so keep per-user data out.
public/logo.png at /logo.pngapp.use(express.static('public')); app.use('/static', express.static('public')); TipUse path., because the path is relative to where you start node.
TrapExpress 5 ignores dotfiles by default, so .well-known files return 404.
Asked in interviews
AskedHow do you serve static files in Express.js?Accept headerres.format({ 'text/html': fn });req.accepts(['json', 'html'])Tipres.format() adds Vary: Accept, so caches keep the versions apart.
TrapWith no match and no default callback, Express passes a 406 error to next().
Asked in interviews
AskedHow do you implement content negotiation in Express.js?app.use(express.json()); express.urlencoded({ extended: true })bodyParser.json() TipA body over limit, 100kb by default, gets 413.
TrapWithout a parser, req.body is undefined. File forms need multer.
Asked in interviews
AskedWhat is the purpose of body-parser middleware?body('email').isEmail() 400validationResult(req) matchedData(req) Extra fields such as isAdmin stay out.TrapChains only record errors. They never reject a request on their own.
Asked in interviews
AskedHow do you implement data validation in Express.js?req.fileupload.single('file') req.filesupload.array('photos') multer({ limits: { fileSize } })Trapfile. comes from the client, so treat it as untrusted.
Asked in interviews
AskedHow do you handle file uploads in Express.js?Bearer tokenjwt.verify(token, secret, cb)app.get('/me', auth, fn);TipOn success, set req.user to the decoded payload.
Trap401 means a missing or bad token. 403 means a known user without permission.
Asked in interviews
AskedHow do you implement authentication middleware?authorize('admin', 'manager')router.use(authorize('admin')); TrapRead roles from your database or a verified token, never from the client.
Asked in interviews
AskedHow would you implement role-based access control in Express.js?session({ secret, resave: false, saveUninitialized: false })req.session.userId = user.id;req.session.regenerate(cb) res.cookie('lang', 'en', { httpOnly: true });TipA cookie holds about 4KB in the browser. A session stores data on the server, with only its ID in a cookie.
TrapMemoryStore leaks memory and works in one process. Use Redis or a database.
app.use(cors()); cors({ origin: ['https://a.com'] })cors({ origin, credentials: true })Browsers reject * with credentials.Tipcors() answers the OPTIONS preflight the browser sends first.
TrapCORS only controls what browsers may read. It isn't access control.
Asked in interviews
AskedHow do you enable CORS in Express.js?app.use(helmet()); Content-Security-Policy limits where scripts load from. Strict-Transport-Security forces HTTPS.TipHelmet also removes X-Powered-By.
TrapKeep 'unsafe-inline' out of scriptSrc. Use a nonce or a hash.
Asked in interviews
AskedHow do you implement security headers in Express.js?429rateLimit({ windowMs: 900000, limit: 100 })app.use('/api', limiter);app.set('trust proxy', 1);Tipmax is the older name of limit. Add a stricter limiter on the login route.
TrapThe default store counts per process. With several instances, use Redis.
Asked in interviews
AskedHow do you implement rate limiting in Express.js?With a limit of 100, bursts on each side of a boundary let 200 through.
TrapRedis commands sent one at a time can race. A Lua script runs them atomically.
Asked in interviews
AskedHow do you implement API rate limiting with different strategies?res.set('Cache-Control', 'max-age=60');Use private for per-user data.client.get(key)client.setEx(key, ttl, json)Save only a 200, never a 404.client.del(key)app.use(compression()); TipBody parsers inflate compressed requests. Compression costs CPU, so a busy site compresses at a reverse proxy.
TrapNever cache a per-user response under the URL alone.
mysql.createPool({ connectionLimit: 10 })pool.execute(sql, params)await pool.getConnection() await conn.beginTransaction() await conn.commit()await conn.rollback()conn.release()TipEach process has its own pool, so 4 workers with a limit of 10 can open 40 connections.
TrapA query on the pool runs outside the transaction. Always release conn, or the pool runs out.
.env with a packagerequire('dotenv').config(); .env with no package (20.6+)node --env-file=.env app.jsNODE_ENV=production TrapEvery value is a string, so convert numbers and booleans.
Asked in interviews
AskedHow do you handle environment variables in Express.js?app.use(morgan('combined')); req.get('x-request-id') || randomUUID()AsyncLocalStorage TipIn production, write structured JSON logs to stdout, with Pino.
Trapconsole.log() is synchronous on a terminal or file, which slows a busy app.
app.get('/health', check);200 if it can, 503 if not.process.hrtime.bigint() monitorEventLoopDelay() node --cpu-prof app.jsnode --heap-prof app.jsTipprom-client exposes latency histograms and event loop lag. Never bind node --inspect to a public address.
TrapA liveness check on the database restarts every container in an outage.
503 when a timer firessetTimeout(send503, 10000);res.on('close', clear);Tip503 means the server was slow. 408 means the client was slow to send.
TrapThe timeout doesn't stop the handler. Check res.headersSent, and abort fetch() calls.
Asked in interviews
AskedHow do you implement request timeout handling?process.on('SIGTERM', stop);server.close(cb); setTimeout(() => process.exit(1), 10000);TipFail the readiness check first, and close the pool before process.exit(0).
Asked in interviews
AskedHow do you implement graceful shutdown in Express.js?cluster.fork();cluster.isPrimary It replaced cluster.isMaster .os.availableParallelism() TipPM2 does the same with -i max. Clustering also multiplies memory and database connections.
TrapWorkers share no memory. Keep sessions and counters in Redis.
Asked in interviews
AskedHow do you implement clustering in Express.js for better performance?req. Service holds the logic. Repository talks to the database.app.js, listen in server.js.TrapKeep req and res out of services, so jobs and tests can call them without HTTP.
Asked in interviews
AskedHow would you structure a large Express.js application?request(app).post('/users').expect(201) swaggerJsdoc(options) /api-docsswaggerUi.setup(specs) TipComments can drift from the code. Spec-first means you write openapi.yaml by hand.
TrapUse a separate test database, never a shared one.
app.use('/api/v2', v2Router);next('route')TipA header keeps one URL per resource, but caches keyed on the URL can't tell versions apart.
TrapPlain next() stays on the same route, so v1 would answer every version.
Asked in interviews
AskedHow do you implement custom middleware for API versioning?http.createServer(app) socketIo(server) server.listen(3000) TipSocket.IO has its own protocol, so plain WebSocket clients can't connect. For raw WebSockets, use ws.
Trapapp.listen() would create a second server that Socket.IO isn't attached to.
Asked in interviews
AskedHow do you implement WebSocket support with Express.js?new CircuitBreaker(fn, { timeout: 3000 })TrapRetry only idempotent calls such as GET. A retried POST can run twice.
Asked in interviews
AskedHow do you implement microservices communication with Express.js?TipNestJS runs on Express by default, or on Fastify.
TrapExpress has no built-in validation or structure, so large codebases drift.
Asked in interviews
AskedWhen would you choose Express over NestJS or Fastify?Nothing matches. Try a shorter word, or clear the search.
With Pro, you can:
Already have Pro? Sign in