Node.js Backend Development for Mobile App

NOVASOLUTIONS.TECHNOLOGY is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
Node.js Backend Development for Mobile App
Medium
from 1 week to 3 months
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Node.js Backend Development for Mobile Applications

A mobile app without a backend is just offline notes. Once users appear, data sync, push notifications, payments — you need a server. Node.js + TypeScript is a pragmatic choice for most mobile backends: fast startup, JSON-native, enormous ecosystem, one language for the team if frontend is also TypeScript.

Stack and Components

Fastify or Express. Express is familiar and documented everywhere. Fastify is faster (20–30% higher throughput in tests), schema-first validation via JSON Schema, out-of-the-box TypeScript support. For new projects, choose Fastify.

// Fastify + TypeScript + Zod validation
import Fastify from 'fastify';
import { z } from 'zod';

const app = Fastify({ logger: true });

const CreatePostSchema = z.object({
  title: z.string().min(1).max(200),
  content: z.string().min(1),
  authorId: z.string().uuid(),
});

app.post('/posts', async (request, reply) => {
  const body = CreatePostSchema.parse(request.body);
  const post = await postService.create(body);
  return reply.status(201).send(post);
});

PostgreSQL + Prisma ORM. Prisma provides type-safe queries from TypeScript schema:

model User {
  id        String   @id @default(uuid())
  email     String   @unique
  posts     Post[]
  createdAt DateTime @default(now())
}
const user = await prisma.user.findUnique({
  where: { id: userId },
  include: { posts: { take: 10, orderBy: { createdAt: 'desc' } } },
});

Prisma Studio — built-in GUI for data inspection during development. Prisma Migrate — database schema versioning via migration files.

Mobile Client Authentication

For mobile apps — JWT with short access token (15 min) and long refresh token (30 days) in secure storage on device. Rotate refresh token on each use.

import jwt from 'jsonwebtoken';

export const generateTokens = (userId: string) => ({
  accessToken: jwt.sign({ sub: userId, type: 'access' }, process.env.JWT_SECRET!, {
    expiresIn: '15m',
  }),
  refreshToken: jwt.sign({ sub: userId, type: 'refresh' }, process.env.JWT_REFRESH_SECRET!, {
    expiresIn: '30d',
  }),
});

// Verification middleware
export const authMiddleware = async (request: FastifyRequest, reply: FastifyReply) => {
  const token = request.headers.authorization?.replace('Bearer ', '');
  if (!token) return reply.status(401).send({ error: 'Unauthorized' });
  try {
    const payload = jwt.verify(token, process.env.JWT_SECRET!) as JwtPayload;
    request.userId = payload.sub!;
  } catch {
    return reply.status(401).send({ error: 'Invalid token' });
  }
};

Store refresh token in database (refresh_tokens table) — allows invalidating all user sessions on password change or logout from all devices.

Push Notifications via Firebase Admin SDK

import * as admin from 'firebase-admin';

admin.initializeApp({ credential: admin.credential.cert(serviceAccount) });

export const sendPushNotification = async (
  fcmToken: string,
  title: string,
  body: string,
  data?: Record<string, string>
) => {
  const message: admin.messaging.Message = {
    token: fcmToken,
    notification: { title, body },
    data,
    apns: {
      payload: { aps: { sound: 'default', badge: 1 } },
    },
    android: {
      priority: 'high',
      notification: { sound: 'default' },
    },
  };
  return admin.messaging().send(message);
};

For bulk sends — sendEachForMulticast with batches of 500 tokens. Remove invalid tokens (messaging/registration-token-not-registered) from database.

Realtime: WebSocket or Server-Sent Events

Chat, realtime likes, delivery status — require persistent connections. WebSocket via ws or socket.io:

import { WebSocketServer } from 'ws';

const wss = new WebSocketServer({ server: httpServer });
const connections = new Map<string, WebSocket>();

wss.on('connection', (ws, request) => {
  const userId = getUserIdFromRequest(request);
  connections.set(userId, ws);

  ws.on('close', () => connections.delete(userId));
});

export const notifyUser = (userId: string, event: object) => {
  const ws = connections.get(userId);
  if (ws?.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify(event));
  }
};

For horizontal scaling (multiple instances), WebSocket connection binds to specific server — need Redis Pub/Sub for broadcasting between instances.

Infrastructure

Docker + docker-compose for local development. PM2 or Docker for production. PostgreSQL main database, Redis for cache and queues (BullMQ). S3 for files.

API structure:

src/
  modules/
    users/        # controller, service, repository, dto
    posts/
    notifications/
  shared/
    middleware/
    guards/
    utils/
  app.ts
  server.ts

Layering: controller → service → repository. Service doesn't know HTTP context — tests purely via Jest.

Common Mistakes

Blocking operations in event loop. JSON.parse large file, synchronous fs.readFileSync per request — blocks all others. Heavy operations go to worker threads or offload to queue.

N+1 in Prisma. Query post list without include → separate query for each post's author. Solution: always use include or Prisma $queryRaw with JOIN for complex cases.

No rate limiting. Mobile client sends 100 requests per second on bad network code — server crashes. Fastify Rate Limit (@fastify/rate-limit) + Redis for distributed limiting.

What's Included in Development

API contract design (OpenAPI/Swagger). Infrastructure setup (database, Redis, Docker). Auth implementation (JWT + refresh). CRUD modules per app requirements. Push notifications. CI/CD configuration. API documentation.

Timeline

MVP backend (Auth + 3–5 resources + push): 2–3 weeks. Full backend with realtime, payments, files: 1–3 months. Pricing calculated after functional requirements review.