Node.js Foundations·From script to service

Deploying a Node service

Ship a service that reports health, shuts down gracefully and separates build from runtime.

Intermediate 12 min read Lesson 5 of 300 Challenge included
What you will be able to do
  • Keep build tools out of the runtime dependency set.
  • Expose a /health endpoint for readiness checks.
  • Handle SIGTERM and SIGINT to close the server cleanly.
  • Drive differences between environments with variables, not code changes.

In plain English

Deploying a server means running it somewhere other than your laptop, so it must behave well under a process manager. Build dependencies such as a compiler or test runner are needed only while building, while runtime dependencies are needed to run the service. A health endpoint is a small route that returns ok so a load balancer can tell whether the service is alive. Graceful shutdown means stopping new requests and finishing in-flight ones when the process receives a signal such as SIGTERM. Structured logs and environment variables keep the deployed service configurable and observable.

Step by step

  1. 1Install build tools as dev dependencies so production installs skip them.
  2. 2Add a /health route that reports the service state.
  3. 3Listen for SIGTERM and SIGINT and close the server.
  4. 4Set a timeout so a stuck server still exits eventually.
server.tsTypeScript
import { createServer } from 'node:http'

const port = Number(process.env.PORT ?? 3000)

const server = createServer((request, response) => {
  if (request.url === '/health') {
    response.writeHead(200, { 'content-type': 'application/json' })
    return response.end(JSON.stringify({ status: 'ok' }))
  }
  response.writeHead(404)
  response.end()
})

server.listen(port, () => {
  console.log('Listening on ' + port)
})

function shutdown(signal: string) {
  console.log('Received ' + signal + ', closing server')
  server.close(() => {
    console.log('Server closed')
    process.exit(0)
  })
  setTimeout(() => {
    console.error('Forced shutdown after timeout')
    process.exit(1)
  }, 10_000).unref()
}

process.on('SIGTERM', () => shutdown('SIGTERM'))
process.on('SIGINT', () => shutdown('SIGINT'))

Common mistakes

  • Shipping test runners and compilers to production bloats the image and widens the attack surface.
  • Ignoring SIGTERM makes a deploy kill the process mid-request and lose work.
  • Returning ok from /health even when the database is down hides a real outage.
  • Hard-coding ports and URLs means the service cannot move between environments.
Your turn

Close the server on a signal

Medium

Add a SIGTERM handler that calls server.close and exits with code 0 when the close callback fires.

JAVASCRIPT · starter
const server = createServer((request, response) => {
  response.end('ok')
})

server.listen(3000)
Check your understanding before moving on.
Knowledge checkQuestion 1

What is the purpose of a /health endpoint?

Select an answer to continue
Study tools

Make it yours.

Keep a private note for this lesson, then turn the key ideas into flashcards you can revisit.

Sign in to save notes and flashcards.Both are private to your account and stay with your progress.
Sign in
Finished reading?

Lock in what you just learned.

Mark this lesson complete to save your place and move one step closer to the certificate.

Next: The runtime and modules
Lesson 5 of 300 · 0% of course