Node.js applications

Node.js, built and run beside your PHP.

We build APIs, server-rendered sites, real-time services and workers in Node, and run them on the same servers as your PHP sites, behind one Nginx.

What we build in Node

Five kinds of work, each one here because Node suits it.

  1. 01

    Express

    Small, direct APIs and back ends: a few routes, clear middleware, nothing hidden.

    APIs and back ends
  2. 02

    NestJS

    Larger services with modules, dependency injection and typed contracts in TypeScript, for code a team will grow for years.

    Structured services
  3. 03

    Next.js · Nuxt

    Server rendering for React and Vue: pages arrive ready for search engines and a fast first view, then behave like an app.

    Server-rendered sites
  4. 04

    Socket.IO · WebSockets

    Chat, notifications, live dashboards and tracking that update the moment something changes, over one open connection.

    Real time
  5. 05

    Workers and queues

    Background jobs, scheduled tasks and queue consumers on Redis that keep slow work out of the request.

    Background work

Why Node is good at waiting

A Node process runs your JavaScript on one thread and hands the waiting - disk, network, database - to the system. That is how one process keeps many connections open at once.

The Node.js event loop, simplified
  1. Your code runs on the call stack, one function at a time.
  2. Slow work leaves the thread: files, DNS and hashing go to the libuv pool, and sockets are watched by the operating system.
  3. When the work is done, its callback waits in the task queue.
  4. Before the next task, every promise callback in the microtask queue runs.
  5. The loop turns through its phases and takes the next task.

PHP and Node on one server

Nginx answers every request and sends each path to the process that owns it. Your PHP site and your Node service share the machine, the database and the certificate - not each other's memory.

An example of one server running both

Which one for which job

We build in both, so the answer comes from the work, not from a habit.

Reach for PHP when

  • The site is mostly pages, forms and an admin: shops, content sites, business systems.
  • You want WordPress, WooCommerce or Laravel and everything already built for them.
  • Each request stands on its own and finishes quickly.
  • The people who will maintain it already know PHP.

Reach for Node when

  • Connections stay open: chat, live dashboards, notifications, tracking.
  • React or Vue pages are rendered on the server with Next.js or Nuxt.
  • The service mostly waits on other APIs and streams data through.
  • One language in the browser and on the server helps your team.

Often the answer is both

PHP keeps the site, the shop and the admin; a small Node service takes the live part beside it. Both read the same database and sit behind the same Nginx.

Releases without a gap

A new release starts next to the old one, proves it is healthy, and only then takes the traffic. The old workers finish the requests they already hold before they stop.

  • Visitors served
  • Current release
  • New release
  1. 01

    Fetch and install

    git pull && npm ci

    Exact versions from the lockfile, nothing newer by surprise.

  2. 02

    Build

    npm run build

    TypeScript and assets are compiled before anything restarts.

  3. 03

    Start beside the old

    pm2 reload app

    The new release boots next to the one still serving.

  4. 04

    Wait until ready

    wait_ready: true

    It must answer its health check before it receives a visitor.

  5. 05

    Take the traffic

    cluster → new workers

    New connections go to the new release.

  6. 06

    Drain the old

    SIGINT → server.close()

    Old workers finish the requests they hold, then exit.

If the new release fails its health check, it never takes traffic: the old one simply keeps serving.

The server around the code

What keeps a Node service up is written down on the server, in files we maintain and you can read.

  • /etc/nginx/sites-enabled/app.conf

    Reverse proxy

    TLS, compression, cached static files and WebSocket upgrades, in front of every process.

  • /srv/app/ecosystem.config.js

    Process manager

    PM2 keeps the process alive, restarts it if it crashes, and uses every core in cluster mode. Where one process is enough, a systemd unit does the same job.

  • /srv/app/.env (0600)

    Environment and secrets

    Keys and passwords live outside the code and outside git, readable only by the application's own user.

  • /srv/app/package-lock.json

    Dependency audit

    npm audit on every release; upgrades are read and tested before they reach production.

  • /srv/app/.nvmrc

    Node LTS upgrades

    The app runs on a Long Term Support release, and we move it to the next one before the old one leaves support.

  • /var/log/app/

    Logs and monitoring

    Structured logs, rotated, with an alert when the process restarts, memory climbs or errors rise.

Tell us what your Node app has to do

A new service, a Next.js site, or an app that already runs somewhere and needs a proper home. We look at it and quote it after a short conversation.