If you're building a Node.js / Express app using Turso (@libsql/client) and notice that nodemon isn't updating your newly added routes, you might have run into a very common development trap!
You might see things like:
-
Cannot GET /new-routeeven though you just wrote the code for it. -
EADDRINUSE: address already in use :::3000hiding in your terminal logs.
🐛 What is happening?
To make queries fast, the @libsql/client holds a persistent, open socket connection to your Turso database.
Because Node.js is designed to never exit as long as there is an active background process (like a database connection), whenever nodemon tries to restart your app, the old process refuses to die.
The old process becomes a "zombie" that keeps running on Port 3000, preventing your updated code from taking over the port.
🛠️ The Solution: Graceful Shutdown
To fix this, you don't need a new package. You just need to tell your Node.js app to close the database connection whenever nodemon sends the restart signal (SIGUSR2).
Step 1: Export your server instance
Modify your app.listen so you have a reference to the running server.
const PORT = process.env.PORT || 3000;
// Change this:
// app.listen(PORT, () => console.log('Running...'))
// To this:
const server = app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Step 2: Add the Graceful Shutdown Logic
At the very bottom of your server.ts (or index.ts), add this cleanup code. It listens for termination signals, closes the database connection, shuts down Express, and finally exits the process.
import { tursoClient } from "./config/turso.js"; // Import your DB client
const shutdown = async () => {
console.log("Shutting down gracefully...");
// 1. Close your database connections
// If using Turso:
tursoClient.close();
// 2. Shut down the express server
server.close(() => {
// 3. Exit the process successfully so nodemon can restart
process.exit(0);
});
};
// Handle Ctrl+C (Terminal Quit)
process.on("SIGINT", shutdown);
// Handle System or Docker shut down
process.on("SIGTERM", shutdown);
// Handle Nodemon restarts
process.once("SIGUSR2", async () => {
await shutdown();
});
Step 3: Clear any lingering Zombie Processes
If you've been experiencing this bug, you likely have hidden processes still holding your port.
If you are on Windows, run this in PowerShell:
npx kill-port 3000
On Mac/Linux, run:
killall node
Now, run npm run dev again. Every time you save your file, nodemon will cleanly shut down the old server and start the new one instantly! Happy coding! 🚀
Top comments (0)