hapi — How to Correctly Stop Your Server and Close Existing Connections

Actively maintained applications get started and stopped very often. It’s not like the operating system of your web server that doesn’t get touched for years once set up ;-) Especially during development, you’re usually starting a local instance of your app multiple times a day!

Stopping a local instance of your app doesn’t require a lot of attention. Just kill the process and you’re done. In production, you want to avoid downtime and certainly data loss. No interruptions for the user!

This guide shows you how to correctly finish and close existing connections and afterwards shut down the hapi server.

hapi Series Overview

Correctly Stop Your hapi Server

Depending on your application setup, you might want to gracefully stop your hapi server and close existing requests, background processing, database interactions, and so on before stopping the actual server process. Precisely, you want to do the actual application shutdown first and ultimately stop the server once everything else has finished.

To correctly tear down the hapi server, you should listen on the SIGINT signal which is emitted by pressing CRTL + C on your keyboard or when stopping the process using your process manager or init system. At the moment you receive a SIGINT in your application you can use hapi’s server.stop() method which waits for open connections to be processed and shuts down afterwards.

The following code snippet illustrates a simple example of starting a hapi server and waiting for the signal to stop the process.

hapi v17

const Hapi = require('hapi')

const server = new Hapi.Server({  
  host: 'localhost',
  port: 3000,
})

async function start () {  
  // start your server
  try {
    await server.start()
  } catch (err) {
    console.error(err)
    process.exit(1)
  }

  console.log('Server running at: ', server.info.uri)
}

start()

// listen on SIGINT signal and gracefully stop the server
process.on('SIGINT', function () {  
  console.log('stopping hapi server')

  server.stop({ timeout: 10000 }).then(function (err) {
    console.log('hapi server stopped')
    process.exit((err) ? 1 : 0)
  })
})

hapi v16

const hapi = require('hapi')  
const server = new hapi.Server()

server.connection({  
  host: 'localhost',
  port: 3000,
})

server.start((err) => {  
  if (err) {
    throw err
  }

  console.log('Server running at:', server.info.uri)
})

// listen on SIGINT signal and gracefully stop the server
process.on('SIGINT', function () {  
  console.log('stopping hapi server')

  server.stop({ timeout: 10000 }).then(function (err) {
    console.log('hapi server stopped')
    process.exit((err) ? 1 : 0)
  })
})

The interesting part is the listener process.on('SIGINT', …) and its function body. Once the SIGINT is received, call hapi’s server.stop() method to reject incoming requests and just finish up existing ones.

The stop method accepts an options object and an optional error-only callback (function (error)) . If you skip the callback parameter on server.stop(), a promise is returned (as we use within the example above).

Available Options

  • timeout: milliseconds, default = 5000 (= 5 seconds). Timeout before forcefully stopping the server

timeout is the only option available to customize hapi’s shutdown procedure. That’s the time interval hapi waits until all connections should be closed. Once the time is up, hapi forcefully closes all connections.

Timeout on Single Instances?

As described above, once you initiate the server stop all existing connections get closed and hapi waits at most the defined timeout interval to finish running tasks. Once the timeout is up, the callback/promise returns and still existing processings get interrupted.

Let’s say you want to restart your single hapi server instance with a considerable timeout of 30 seconds and there’s a client that requires a lot of processing on server side. Once you submitted the restart command, hapi will wait for at most 30 seconds to finish the processing and close the connection. Other requests within these 30 seconds interval will be rejected and need to wait or request again to be accepted properly.

Outlook

Stopping your hapi server with grace is very important in production environments. Keep service interruptions down to a minimum und most importantly don’t lose user data due to headless server stops. Hapi provides the functionality to gracefully stop the server process and allows you to customize the waiting time before the process is teared down.

In the next tutorial, you’ll learn how to avoid service interruptions in your hapi app and benefit from zero downtime restarts with the help of PM2.

We appreciate your feedback and love to help you if there’s a question or bug that doesn’t let you sleep. Let us know in the comments or on twitter @futurestud_io.

Make it rock & enjoy coding!

Explore the Library

Find interesting tutorials and solutions for your problems.