## TL;DR
Run jest with `--detectOpenHandles` to get a report of what is keeping the event loop alive: usually a database connection, an HTTP server, a timer, or a socket that was never closed. The fix is almost always to close the resource in an `afterAll` hook (or use `server.close()` / `client.disconnect()` / `clearInterval` where it was created). Do not reach for `--forceExit` as the real fix; it masks leaks that will bite you in CI.

## The query
```text
jest open handles keeping process alive: how to find
```

## Use this when
- Jest prints test results but the process never exits
- CI jobs hang or time out after all tests pass
- You see "Jest did not exit" warnings in output
- You suspect leaked timers, servers, or DB connections

## Not for
- Tests that fail with assertion errors
- Slow tests that still exit cleanly
- Memory leaks during the test run itself

## Steps
1. Re-run with `npx jest --detectOpenHandles` and read the reported handles and their creation stacks. Expected output: jest prints each open handle with a stack trace pointing at where it was created.
2. Map each handle to its owner: DB clients, `http.createServer` without `close()`, `setInterval` without `clearInterval`, websocket or redis clients left connected. Expected output: a list of 1-3 resources tied to specific test files or setup modules.
3. Close each resource in an `afterAll` hook in the file (or setup file) that created it, e.g. `await db.disconnect()` or `server.close()`. Expected output: the resource is released when the test file finishes.
4. Re-run without `--detectOpenHandles` and confirm jest exits on its own within a few seconds of the results. Expected output: process exits cleanly, exit code 0, no "did not exit" warning.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_-x9E7_gWYzGKN5Z9WABfIw
