{"id":15684903,"url":"https://github.com/sholladay/handle-quit","last_synced_at":"2025-10-16T10:37:42.932Z","repository":{"id":57260503,"uuid":"69147428","full_name":"sholladay/handle-quit","owner":"sholladay","description":"Support graceful stop in your app","archived":false,"fork":false,"pushed_at":"2019-12-31T04:51:49.000Z","size":23,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-02T03:07:50.701Z","etag":null,"topics":["deployment","pm2","reload","server","zero-downtime"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sholladay.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-09-25T06:20:42.000Z","updated_at":"2021-10-23T20:13:15.000Z","dependencies_parsed_at":"2022-08-25T05:02:14.629Z","dependency_job_id":null,"html_url":"https://github.com/sholladay/handle-quit","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sholladay%2Fhandle-quit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sholladay%2Fhandle-quit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sholladay%2Fhandle-quit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sholladay%2Fhandle-quit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sholladay","download_url":"https://codeload.github.com/sholladay/handle-quit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sholladay%2Fhandle-quit/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":258970710,"owners_count":22786052,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deployment","pm2","reload","server","zero-downtime"],"created_at":"2024-10-03T17:22:21.355Z","updated_at":"2025-10-16T10:37:37.882Z","avatar_url":"https://github.com/sholladay.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# handle-quit [![Build status for Handle Quit](https://travis-ci.com/sholladay/handle-quit.svg?branch=master \"Build Status\")](https://travis-ci.com/sholladay/handle-quit \"Builds\")\n\n\u003e Support [graceful stop](http://pm2.keymetrics.io/docs/usage/signals-clean-restart/#graceful-stop) in your app\n\nRespond to shutdown signals, so a process manager can reload your app without dropping any connections.\n\n## Why?\n\n - Friendly to your users.\n - Easy to use and reason about.\n - Helps you do easy [zero downtime](https://futurestud.io/tutorials/pm2-cluster-mode-and-zero-downtime-restarts#zerodowntimedeployments) deployments.\n\n## Install\n\n```sh\nnpm install handle-quit --save\n```\n\n## Usage\n\nGet it into your program.\n\n```js\nconst handleQuit = require('handle-quit');\n```\n\nMake sure your program shuts down gracefully or quickly, as necessary.\n\n```js\nhandleQuit(() =\u003e {\n    server.close();\n});\n```\n\nNote that calling [`process.exit()`](https://nodejs.org/api/process.html#process_process_exit_code) is discouraged. Instead, you should close any server and database connections and let Node exit on its own, which it does automatically when it has no more work left to do.\n\nIf you are worried about the process hanging and never cleanly exiting, you are encouraged to use your framework's [stop timeout](https://hapi.dev/api/#server.stop()).\n\n## Use with PM2\n\nTo achieve zero downtime deployments, [PM2](https://github.com/Unitech/pm2) needs to shutdown your app without dropping any connections. It sends a [`SIGINT` signal](https://nodejs.org/api/process.html#process_signal_events) to trigger the shutdown process. However, by default, Node reacts to this by exiting immediately, and thus in-progress connections may be dropped.\n\nThese problems can be fixed by using `handleQuit()` in the main entry of your CLI or server, as shown above, to override the default `SIGINT` behavior and deny _new_ connections on the first `SIGINT`, while allowing any in-progress connections to finish. This is known as [graceful stop](http://pm2.keymetrics.io/docs/usage/signals-clean-restart/#graceful-stop).\n\nPM2 waits for apps that gracefully stop to quit before replacing them with a new deployment when using `pm2 reload`.\n\n```console\n$ pm2 start app.js --kill-timeout 6000\n```\n\nJust in case something goes wrong, `--kill-timeout` tells PM2 how long it should wait for the process to exit before considering the process hung / frozen, in which case it will force kill the process. You should ensure that `--kill-timeout` is greater than or equal to any stop timeouts used in your app.\n\nTo support graceful _start_, see [app-ready](https://github.com/sholladay/app-ready).\n\n## API\n\n### handleQuit(listener)\n\nListens for [POSIX signals](https://en.wikipedia.org/wiki/Unix_signal#POSIX_signals) (`SIGINT`and `SIGTERM`) and calls the `listener` function on the first signal to perform a graceful shutdown. Calls [`process.exit()`](https://nodejs.org/api/process.html#process_process_exit_code) with an appropriate error code on any further signals that are received to perform an ungraceful shutdown. Relevant messages are also printed to the console.\n\n#### listener\n\nType: `function`\n\nA function that will gracefully shutdown your program. A common example is [Server#close()](https://nodejs.org/api/http.html#http_server_close_callback).\n\n## Related\n\n - [app-ready](https://github.com/sholladay/app-ready) - Support [graceful start](http://pm2.keymetrics.io/docs/usage/signals-clean-restart/#graceful-start) in your app\n\n## Contributing\n\nSee our [contributing guidelines](https://github.com/sholladay/handle-quit/blob/master/CONTRIBUTING.md \"Guidelines for participating in this project\") for more details.\n\n1. [Fork it](https://github.com/sholladay/handle-quit/fork).\n2. Make a feature branch: `git checkout -b my-new-feature`\n3. Commit your changes: `git commit -am 'Add some feature'`\n4. Push to the branch: `git push origin my-new-feature`\n5. [Submit a pull request](https://github.com/sholladay/handle-quit/compare \"Submit code to this project for review\").\n\n## License\n\n[MPL-2.0](https://github.com/sholladay/handle-quit/blob/master/LICENSE \"License for handle-quit\") © [Seth Holladay](https://seth-holladay.com \"Author of handle-quit\")\n\nGo make something, dang it.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsholladay%2Fhandle-quit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsholladay%2Fhandle-quit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsholladay%2Fhandle-quit/lists"}