# Claude-Mem Graceful Shutdown: A Multi-Step Strategy to Prevent Data Loss During Restarts

> Discover Claude-Mem's 8-step graceful shutdown strategy. Learn how it prevents data loss by closing connections flush sessions write databases and terminate processes before exiting.

- Repository: [Alex Newman/claude-mem](https://github.com/thedotmack/claude-mem)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Claude-Mem implements a coordinated 8-step graceful shutdown sequence in [`src/services/infrastructure/GracefulShutdown.ts`](https://github.com/thedotmack/claude-mem/blob/main/src/services/infrastructure/GracefulShutdown.ts) that ensures all HTTP connections close, sessions flush, databases write pending data, and child processes terminate before the process exits with code 0.**

Graceful shutdown is critical for persistent AI applications like Claude-Mem to prevent memory loss and data corruption during restarts. The `thedotmack/claude-mem` repository implements a robust, multi-phase shutdown protocol that systematically releases resources rather than terminating abruptly. This approach ensures that vector store data, session state, and database writes complete successfully even when the service receives termination signals.

## Signal Handling Architecture

The shutdown process begins in [`src/services/worker-service.ts`](https://github.com/thedotmack/claude-mem/blob/main/src/services/worker-service.ts) where the `WorkerService` class registers handlers for `SIGTERM`, `SIGINT`, and `SIGHUP` (on Unix systems). When the operating system sends these signals, the handlers set an internal `isShuttingDown` flag and invoke the `shutdown()` method.

This design prevents race conditions by ensuring that only one shutdown path executes, even if multiple signals arrive simultaneously. The signal handlers use a reference object pattern to share state safely between the handler context and the service instance.

### Signal Handler Registration

The `registerSignalHandlers()` method in [`worker-service.ts`](https://github.com/thedotmack/claude-mem/blob/main/worker-service.ts) (lines 52-78) implements this pattern:

```typescript
private registerSignalHandlers(): void {
  const shutdownRef = { value: this.isShuttingDown };
  const handler = createSignalHandler(() => this.shutdown(), shutdownRef);

  process.on('SIGTERM', () => {
    this.isShuttingDown = shutdownRef.value;
    handler('SIGTERM');
  });
  process.on('SIGINT', () => {
    this.isShuttingDown = shutdownRef.value;
    handler('SIGINT');
  });
  // SIGHUP handling omitted for brevity…
}

```

## The 8-Step Shutdown Sequence

The core logic resides in [`src/services/infrastructure/GracefulShutdown.ts`](https://github.com/thedotmack/claude-mem/blob/main/src/services/infrastructure/GracefulShutdown.ts) within the `performGracefulShutdown()` function. This utility executes an ordered sequence that prioritizes data integrity over speed, ensuring that dependent services shut down in the correct order.

### Step 1 – Child Process Enumeration

Before releasing resources, the system captures the PIDs of all child processes using `getChildProcesses()`. This snapshot ensures that even if child processes detach during shutdown, they can still be terminated later.

```typescript
const childPids = await getChildProcesses(process.pid);

```

### Step 2 – HTTP Server Shutdown

The `closeHttpServer()` function (lines 111-125) first closes all active connections with `server.closeAllConnections()`, then shuts down the server itself. A platform-specific delay accommodates Windows socket release behavior, preventing port conflicts on restart.

### Steps 3-6 – Service Layer Cleanup

The sequence continues through the application stack:

- **Session Manager**: `sessionManager.shutdownAll()` flushes and terminates all active sessions
- **MCP Client**: `mcpClient.close()` signals child processes to exit gracefully
- **Chroma Server**: `chromaServer.stop()` halts the local vector store
- **Database Manager**: `dbManager.close()` ensures SQLite/ChromaSync writes complete

### Step 7 – Force Kill Remaining Children

Any child processes still running after the graceful signals receive a force kill via `forceKillProcess()`. The system waits up to 5 seconds for confirmation before proceeding.

### Step 8 – Final Cleanup

The process removes its PID file and logs completion. All exit paths use code 0 to prevent Windows Terminal from keeping tabs open, as implemented in [`worker-service.ts`](https://github.com/thedotmack/claude-mem/blob/main/worker-service.ts) lines 923-1085.

## Key Implementation Files

| File | Role |
|------|------|
| [`src/services/infrastructure/GracefulShutdown.ts`](https://github.com/thedotmack/claude-mem/blob/main/src/services/infrastructure/GracefulShutdown.ts) | Central implementation of the multi-step shutdown sequence |
| [`src/services/worker-service.ts`](https://github.com/thedotmack/claude-mem/blob/main/src/services/worker-service.ts) | Registers OS signals and initiates shutdown |
| [`src/services/infrastructure/ProcessManager.ts`](https://github.com/thedotmack/claude-mem/blob/main/src/services/infrastructure/ProcessManager.ts) | Helpers for enumerating and terminating child processes |
| [`src/services/infrastructure/HealthMonitor.ts`](https://github.com/thedotmack/claude-mem/blob/main/src/services/infrastructure/HealthMonitor.ts) | Monitors shutdown exit codes for Windows compatibility |
| [`tests/infrastructure/graceful-shutdown.test.ts`](https://github.com/thedotmack/claude-mem/blob/main/tests/infrastructure/graceful-shutdown.test.ts) | Unit tests verifying each shutdown step |

## Summary

Claude-Mem's graceful shutdown approach prevents data loss through systematic resource management:

- **Signal-driven initiation**: `SIGTERM`, `SIGINT`, and `SIGHUP` handlers in [`worker-service.ts`](https://github.com/thedotmack/claude-mem/blob/main/worker-service.ts) trigger an orderly shutdown rather than abrupt termination
- **Ordered resource release**: The 8-step sequence in [`GracefulShutdown.ts`](https://github.com/thedotmack/claude-mem/blob/main/GracefulShutdown.ts) prioritizes data integrity by closing HTTP connections, flushing sessions, and writing database changes before terminating child processes
- **Child process safety**: Enumeration and force-kill mechanisms ensure no orphaned processes remain to hold ports or corrupt data files
- **Cross-platform compatibility**: Windows-specific delays and exit code 0 handling prevent socket conflicts and terminal tab persistence issues

## Frequently Asked Questions

### What signals trigger Claude-Mem's graceful shutdown?

The system responds to `SIGTERM`, `SIGINT`, and `SIGHUP` (Unix only) signals. These are registered in [`src/services/worker-service.ts`](https://github.com/thedotmack/claude-mem/blob/main/src/services/worker-service.ts) by the `registerSignalHandlers()` method, which ensures that any termination request initiates the coordinated shutdown sequence rather than killing the process immediately.

### How does Claude-Mem ensure database writes complete before exiting?

The shutdown sequence explicitly closes the database manager after flushing sessions but before terminating child processes. In [`src/services/infrastructure/GracefulShutdown.ts`](https://github.com/thedotmack/claude-mem/blob/main/src/services/infrastructure/GracefulShutdown.ts), step 6 calls `dbManager.close()`, which ensures all pending SQLite and ChromaSync writes are persisted to disk. This ordering prevents data corruption that could occur if the process exited while writes were in flight.

### Why does Claude-Mem use exit code 0 instead of error codes during shutdown?

Claude-Mem intentionally exits with code 0 to maintain compatibility with Windows Terminal and other process managers. As implemented in [`src/services/worker-service.ts`](https://github.com/thedotmack/claude-mem/blob/main/src/services/worker-service.ts) (lines 923-1085), using exit code 0 prevents Windows Terminal from keeping tabs open after a graceful stop, while still ensuring all cleanup operations complete. This distinguishes intentional restarts from actual crash conditions.

### What happens if a child process refuses to terminate gracefully?

If child processes survive the initial graceful signals, Claude-Mem escalates to force termination. In [`src/services/infrastructure/GracefulShutdown.ts`](https://github.com/thedotmack/claude-mem/blob/main/src/services/infrastructure/GracefulShutdown.ts), step 7 uses `forceKillProcess()` to send termination signals to any remaining child PIDs enumerated at the start of shutdown. The system waits up to 5 seconds for confirmation, ensuring no orphaned processes remain to hold network ports or file locks.