# How Dewy Performs Graceful Restarts for Server Applications

> Discover how Dewy achieves graceful restarts for server applications by intercepting SIGUSR1 and leveraging server-starter to atomically hand over sockets without dropping connections.

- Repository: [Tomohisa Oda/dewy](https://github.com/linyows/dewy)
- Tags: how-to-guide
- Published: 2026-03-06

---

**Dewy performs graceful restarts for server applications by intercepting `SIGUSR1` to trigger a self-sent `SIGHUP`, which leverages the `server-starter` library to atomically hand over listening sockets to a new process without dropping active connections.**

The `linyows/dewy` repository implements a zero-downtime deployment mechanism that allows Go server applications to update without interrupting existing requests. Understanding how Dewy performs graceful restarts for server applications requires examining its Unix signal handling architecture and its integration with the `github.com/lestrrat-go/server-starter` library.

## Understanding Dewy's Graceful Restart Architecture

Dewy’s graceful restart mechanism relies on a coordinated sequence of Unix signals and external library support to achieve zero-downtime deployments. The architecture separates the **trigger signal** (`SIGUSR1`) from the **handoff signal** (`SIGHUP`), allowing the system to distinguish between user-initiated restarts and internal process management.

When Dewy receives `SIGUSR1`, it initiates a self-signaling process that ultimately invokes the `server-starter` library. This library creates a new instance of the server binary while passing the existing listening socket file descriptors to the new process. The old process continues serving existing connections until the new process signals readiness, at which point the old instance terminates gracefully.

## Implementation Details in the Dewy Source Code

The graceful restart logic is implemented across [`dewy.go`](https://github.com/linyows/dewy/blob/main/dewy.go) and [`starter.go`](https://github.com/linyows/dewy/blob/main/starter.go), with specific functions handling signal trapping, restart initiation, and server process management.

### Signal Handling with waitSigs

In [`dewy.go`](https://github.com/linyows/dewy/blob/main/dewy.go) (lines 193–210), the `waitSigs` function establishes a signal notification channel using `signal.Notify`. This channel listens for `SIGHUP`, `SIGUSR1`, `SIGINT`, `SIGTERM`, and `SIGQUIT`. When `SIGUSR1` is received, the function invokes `restartServer` to begin the graceful restart sequence.

The implementation ensures that the signal handler runs in a dedicated goroutine, preventing blocking of the main application loop while waiting for system signals.

### Initiating the Restart with restartServer

The `restartServer` function (lines 473–485 in [`dewy.go`](https://github.com/linyows/dewy/blob/main/dewy.go)) handles the actual restart trigger. It acquires a mutex lock to prevent concurrent restarts, retrieves the current process ID using `os.Getpid()`, and sends `SIGHUP` to itself via `os.FindProcess(pid).Signal(syscall.SIGHUP)`.

This self-signaling approach decouples the user trigger (`SIGUSR1`) from the restart protocol (`SIGHUP`), allowing the `server-starter` library to intercept the `SIGHUP` and manage the process handoff without confusing external signal sources with internal restart coordination.

### Server Process Management with startServer

In [`dewy.go`](https://github.com/linyows/dewy/blob/main/dewy.go) (lines 488–514), the `startServer` function initializes the graceful restart capability by creating a `starter.Starter` instance. It passes the user-provided `StarterConfig` to `starter.NewStarter()`, then invokes `s.Run()` in a background goroutine.

The `github.com/lestrrat-go/server-starter` library manages the `SIGHUP` signal by spawning a new server process, passing the inherited file descriptors for listening sockets, and coordinating the shutdown of the old process only after the new one is ready to accept connections.

### Configuration Structure in starter.go

The `StarterConfig` type defined in [`starter.go`](https://github.com/linyows/dewy/blob/main/starter.go) (lines 10–57) specifies the parameters required for the graceful restart mechanism. Key fields include the command to execute, port numbers to bind, and signal names (`sigonhup`, `sigonterm`) that configure how the `server-starter` library responds to system signals.

This configuration is passed through from Dewy’s main configuration to the underlying library, allowing customization of the restart behavior while maintaining the zero-downtime guarantee.

## Practical Usage: Triggering a Graceful Restart

To perform a graceful restart of a server application managed by Dewy, send the `SIGUSR1` signal to the running Dewy process. This initiates the internal sequence that results in a zero-downtime handoff to a new process.

```bash

# Start Dewy (assumes it manages a web server)

$ dewy run

# Deploy a new artifact (Dewy downloads and updates the 'current' symlink)

# Trigger graceful restart

$ kill -SIGUSR1 $(cat /var/run/dewy.pid)

```

When `SIGUSR1` is received, Dewy’s `waitSigs` function calls `restartServer`, which sends `SIGHUP` to itself. The `server-starter` library intercepts this signal, starts a new instance of the server binary, passes the listening socket file descriptors, and gracefully terminates the old process only after the new one is ready.

For automated deployments, configure your CI pipeline or systemd to send `SIGUSR1` whenever a new release is detected, enabling fully automated zero-downtime updates.

## Summary

- **Signal decoupling**: Dewy uses `SIGUSR1` as the user-facing trigger and `SIGHUP` as the internal handoff signal to separate user commands from process management.
- **Server-starter integration**: The `github.com/lestrrat-go/server-starter` library handles the complex logic of socket passing and process coordination, invoked via `starter.NewStarter` in [`dewy.go`](https://github.com/linyows/dewy/blob/main/dewy.go) (lines 488–514).
- **Zero-downtime guarantee**: The old process continues serving existing connections while the new process initializes, with the handoff occurring only after the new process signals readiness.
- **Core implementation**: Signal handling resides in `waitSigs` (lines 193–210), restart initiation in `restartServer` (lines 473–485), and configuration in [`starter.go`](https://github.com/linyows/dewy/blob/main/starter.go) (lines 10–57).

## Frequently Asked Questions

### What is the difference between SIGUSR1 and SIGHUP in Dewy's restart flow?

Dewy uses `SIGUSR1` as the external trigger for users or automation systems to request a restart, while `SIGHUP` serves as the internal mechanism to execute the handoff. When `SIGUSR1` is received by the `waitSigs` function in [`dewy.go`](https://github.com/linyows/dewy/blob/main/dewy.go), it calls `restartServer`, which sends `SIGHUP` to the same process. This separation allows the `server-starter` library to intercept `SIGHUP` specifically for socket-passing operations while keeping the user interface distinct.

### How does Dewy ensure zero-downtime during server restarts?

Dewy achieves zero-downtime restarts by leveraging the `github.com/lestrrat-go/server-starter` library's socket-passing capability. When `SIGHUP` is triggered, the library starts a new server process and passes the existing listening socket file descriptors to it. The old process continues serving established connections until they complete, while the new process accepts new connections. The old instance terminates only after the new process signals readiness, ensuring no active requests are dropped during the transition.

### Can Dewy perform graceful restarts without the server-starter library?

No, Dewy relies entirely on the `github.com/lestrrat-go/server-starter` library to handle the low-level details of graceful restarts. The `startServer` function in [`dewy.go`](https://github.com/linyows/dewy/blob/main/dewy.go) (lines 488–514) initializes the library via `starter.NewStarter` and executes `s.Run()` to manage the process lifecycle. Without this library, Dewy would not have the socket-passing and process coordination mechanisms required for zero-downtime restarts.

### Where is the graceful restart logic implemented in the Dewy source code?

The graceful restart logic is distributed across two main files in the repository. Signal handling and restart initiation reside in [`dewy.go`](https://github.com/linyows/dewy/blob/main/dewy.go), specifically in the `waitSigs` function (lines 193–210) for signal trapping and `restartServer` (lines 473–485) for triggering the handoff. The integration with the underlying restart mechanism occurs in `startServer` (lines 488–514), which configures the `server-starter` library. Configuration parameters for the restart behavior are defined in [`starter.go`](https://github.com/linyows/dewy/blob/main/starter.go) (lines 10–57) within the `StarterConfig` struct.