Backend Development

Building Scalable Node.js APIs for Mobile Applications

Mobile apps need a backend — and in 2020, Node.js with Express has become the go-to choice for teams that want JavaScript end-to-end. Its non-blocking I/O model handles thousands of concurrent connections efficiently, npm has every library you will ever need, and deploying to AWS, GCP, or Heroku is a five-minute operation. Here’s the architecture of a production-ready mobile API.

Project Structure

src/
├── routes/       # Express route handlers
├── controllers/  # Business logic
├── models/       # Mongoose schemas
├── middleware/   # Auth, validation, error handling
├── config/       # DB connection, env variables
└── app.js        # Express app setup

Authentication with JWT

Mobile apps cannot use session cookies easily — JSON Web Tokens are the standard:

const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');

// Login endpoint
router.post('/login', async (req, res) => {
    const user = await User.findOne({ email: req.body.email });
    if (!user || !await bcrypt.compare(req.body.password, user.password)) {
        return res.status(401).json({ error: 'Invalid credentials' });
    }
    const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, { expiresIn: '7d' });
    res.json({ token });
});

// Auth middleware
const authMiddleware = (req, res, next) => {
    const token = req.headers.authorization?.split(' ')[1];
    try {
        req.user = jwt.verify(token, process.env.JWT_SECRET);
        next();
    } catch {
        res.status(401).json({ error: 'Unauthorized' });
    }
};

Input Validation with express-validator

Never trust mobile app input. Validate every field server-side:

const { body, validationResult } = require('express-validator');

router.post('/users', [
    body('email').isEmail().normalizeEmail(),
    body('password').isLength({ min: 8 }),
], (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() });
    // proceed
});

Rate Limiting

const rateLimit = require('express-rate-limit');
app.use('/api', rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }));

Error Handling

A centralised error handler prevents stack traces leaking to clients. Catch all async errors with a wrapper or use express-async-errors to avoid try-catch in every route.

Environment Variables

Use dotenv for local development and set environment variables directly in your deployment platform. Never commit a .env file.

A well-structured Node.js API is fast to develop, easy to scale horizontally, and fits naturally into a mobile-first product team. With TypeScript (which the community is rapidly adopting), you also gain static typing across your entire stack.

Share this post:
Copied!

Leave a Comment

Your email will not be published.

READY TO BUILD?

Let's Build Something
Amazing Together

Tell us about your project. We'll have a proposal in your inbox within 24 hours.

Free Consultation
NDA Available
Fixed-price Options
Dedicated PM