Running Servers Locally
🐕‍🦺

Running Servers Locally

Description
Some annoying scenarios with local servers
Tags
Node.JS
Date posted
Apr 19, 2020
Image by

Hot reloading

The last few months I have been involved in many Backend projects and it is always interesting to see different approaches that people follow when setting things up. I realised that there are many arguments on the very first step of “how do I run my server”. Every person I meet honestly has different ways of doing that and im like “chillax people… it’s just a command” but you know how sensitive our community is. The one library that has never disappointed me is Nodemon.
 
Nodemon is great for running projects locally as it allows you to do cool stuff like hot reload and works great with typescript. My favourite configuration goes as follows. Open your package.json file and add the following line into your scripts.
 
{
	"dev": "nodemon"
}
 
That way we keep things clean (yes I am talking to you devs that add 20 environment variables in per script) and we have a separate config file that allows us to add whatever we want outside the package.json file. Let’s create a new config file for nodemon.json and add the following:
 
{
	"watch": ["src/server/*"],
	"exec": "node src/server"
}
 
Yes it is that simple! Make sure that you are watching the right folder so that hot reload will work fine! You specify the path(s) inside watch which expects an array of paths. That way every time you save something in any of these paths your server will restart and woohoo you saved a couple of seconds of your life 🎉. You can then specify the commands you want to run in exec. This works great for TypeScript servers as well. Adding "ext": "ts" will tell the server that it also needs to be watching for TypeScript files.
 
{
	"watch": ["src/server/*"],
	"ext": "ts",
	"exec": "ts-node --project tsconfig.json src/server"
}
 
However hot reload can sometimes cause a bit of trouble.
 

Graceful shutdown

One of the downsides of hot reloading is that it can leave connections hanging… That can be especially painful for your wallet if you communicate with other servers. Thankfully things are not that tragic as Node has some internal signals that can help us have better control of what is still running.
 
Signals are processes that your code can listen to and then do something. An example:
 
const express = require("express")
const app = express()
const port = 3000
app.get("/", (req, res) => res.send("Hello World!"))
const server = app.listen(port, () =>
  console.log(`Example app listening at http://localhost:${port}`)
)

process.on("SIGINT", () => {
  server.close(() => {
    console.log("Time to go to sleep")
  })
})
 
If we go to the terminal and kill the server we will notice that straight after doing that, the terminal prints the message “Time to go to sleep”. I know you may be wondering wtf is SIGINT but it stands for interrupt signal (mind blown!!).
 
I still remember this system I was working a couple of years ago where after 4 hot reloads the server would crash. In order to continue with my work I had to wear a unix hat and start googling on how to find a process that runs in port 3000, then copy its id and run another command to kill it… One time this caused 154 active connections to the database and we thought we were being hacked.
 
Probably these connections had been there for a while but you get the point. We found out that on hot reload the signal SIGUSR2 is sent so we followed the same strategy as the example above. The number of active connections dropped dramatically (so did the AWS bill). It also appeared quite useful for more complicated architectures where processes can be killed by other services with SIGTERM.
 
These days it is super simple and fast to get a new server up and running. However this does not mean that everything around maintaining that server is also simple. So yeah better to keep these in mind when building stuff so that you don’t find it the hard way like we did 😂.