# Understanding the Key Components of Dewy's Architecture: A Modular Go Deployment Orchestrator

> Explore Dewy's modular Go architecture. Discover how its central core orchestrates registries and more for zero-downtime deployments.

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

---

**Dewy is a modular Go-based deployment orchestrator that coordinates registries, artifacts, caching, container runtimes, and notifications through a central core to deploy binaries, static assets, or containers with zero-downtime rolling updates.**

Dewy is an open-source deployment tool written in Go that automates the release of applications across multiple formats. Understanding the key components of Dewy's architecture reveals how it maintains flexibility across binary servers, static asset hosting, and containerized workloads while keeping concerns cleanly separated into swappable interfaces.

## Core Orchestration Engine

The heart of Dewy resides in [`dewy.go`](https://github.com/linyows/dewy/blob/main/dewy.go), which defines the `Dewy` struct and its lifecycle methods. This component coordinates the entire deployment workflow, initializing subsystems, scheduling periodic checks, handling OS signals, and driving the deployment loop for both server and container modes.

Key methods include `New` for initialization, `Start` to launch the scheduler and auxiliary services, `Run` for traditional binary deployments, and `RunContainer` for Docker or Podman workloads. The core maintains references to the registry client, cache, notifier, and container runtime, acting as the central dispatcher.

## Configuration Management

All user-provided settings are encapsulated in the `Config` struct defined in [`config.go`](https://github.com/linyows/dewy/blob/main/config.go). This structure defines the deployment command type—**SERVER**, **ASSETS**, or **CONTAINER**—along with registry URLs, container options, hook commands, and notification preferences.

The `DefaultConfig()` function provides sensible defaults, while the CLI layer in [`cli.go`](https://github.com/linyows/dewy/blob/main/cli.go) and [`cmd/dewy/main.go`](https://github.com/linyows/dewy/blob/main/cmd/dewy/main.go) handles flag parsing and config assembly. This separation allows Dewy to run programmatically with a constructed `Config` or via command-line arguments.

## Registry Abstraction Layer

Dewy abstracts artifact sources through the `Registry` interface in [`registry/registry.go`](https://github.com/linyows/dewy/blob/main/registry/registry.go). This interface defines `Current()` to fetch the latest artifact metadata and `Report()` to send deployment status back to the source.

Implementations include [`registry/ghr.go`](https://github.com/linyows/dewy/blob/main/registry/ghr.go) for GitHub Releases, [`registry/oci.go`](https://github.com/linyows/dewy/blob/main/registry/oci.go) for OCI registries, and adapters for S3 and GCS. This modular design allows Dewy to poll for new versions from virtually any artifact storage system without modifying the core logic.

## Artifact Handling

The `artifact` package in [`artifact/artifact.go`](https://github.com/linyows/dewy/blob/main/artifact/artifact.go) provides a download abstraction layer. It handles fetching binaries, tarballs, or OCI images from remote sources and exposes an `io.Reader` interface that integrates with the caching layer.

The `artifact.New` function creates an appropriate handler based on the registry type, while the `Download` method streams content to the local cache. This separation ensures that network I/O concerns remain isolated from deployment orchestration.

## Caching and Persistence (KVS)

Dewy uses the `kvs` package defined in [`kvs/kvs.go`](https://github.com/linyows/dewy/blob/main/kvs/kvs.go) to persist downloaded artifacts and track the current deployment version. The `KVS` interface supports multiple backends: `file` for local filesystem storage, `memory` for ephemeral caching, `redis` for distributed setups, and `consul` for service-discovery-backed storage.

The cache stores artifacts under versioned keys and maintains a `current` reference to track the active deployment, enabling atomic rollbacks and preventing redundant downloads when the registry reports a version already present in the cache.

## Notification System

Deployment visibility is handled by the `notifier` package in [`notifier/notifier.go`](https://github.com/linyows/dewy/blob/main/notifier/notifier.go). The `Notifier` interface defines methods for `Send`, `SendError`, and `SendHookResult`, with concrete implementations for Slack ([`notifier/slack.go`](https://github.com/linyows/dewy/blob/main/notifier/slack.go)), email, and a no-op stub for silent operation.

Notifiers receive context about the deployment—version numbers, artifact sources, and error details—allowing teams to integrate Dewy into existing incident response workflows.

## Container Runtime Integration

For **CONTAINER** command types, Dewy interfaces with Docker or Podman through the `container` package. The `Runtime` interface in [`container/docker.go`](https://github.com/linyows/dewy/blob/main/container/docker.go) and [`container/podman.go`](https://github.com/linyows/dewy/blob/main/container/podman.go) abstracts container lifecycle operations: `Pull`, `Run`, `Stop`, and health-check polling.

This abstraction allows Dewy to manage containerized workloads identically regardless of whether the underlying runtime is Docker or Podman, supporting rolling updates with zero downtime. Users specify their preferred runtime in the `ContainerConfig`, and Dewy instantiates the appropriate implementation via `container.NewDocker` or `container.NewPodman`.

## Supporting Infrastructure Components

### TCP Reverse Proxy

When operating in container mode, Dewy includes an in-process TCP reverse proxy defined in [`dewy.go`](https://github.com/linyows/dewy/blob/main/dewy.go). This component manages rolling updates by dynamically adding and removing backend containers via `addBackend` and `removeBackend` methods while maintaining round-robin routing.

The proxy listens on configured proxy ports and forwards traffic to dynamically allocated container ports, enabling zero-downtime deployments without external load balancers.

### Admin API

Dewy exposes a small HTTP administrative interface defined in [`dewy.go`](https://github.com/linyows/dewy/blob/main/dewy.go) that provides visibility into runtime state. Endpoints include `/api/containers` for listing managed containers and `/api/status` for health checks, enabling integration with external orchestration tools and monitoring systems.

### Server Starter

For **SERVER** command deployments, Dewy leverages `github.com/linyows/server-starter` to manage the user-provided binary. This helper handles graceful restarts, socket passing, and process supervision, ensuring that binary deployments maintain availability during updates.

### Structured Logging

All subsystems report through a centralized logger defined in [`logging/logger.go`](https://github.com/linyows/dewy/blob/main/logging/logger.go). The `Logger` struct provides JSON-encoded output with methods for `Info`, `Error`, and `Debug` levels, ensuring consistent observability across the registry, cache, and container runtime components.

## Execution Flow: How Components Interact

The deployment process follows a clear orchestration pattern that varies by command type.

For **server** and **assets** deployments, the flow begins with the CLI parsing flags in [`cmd/dewy/main.go`](https://github.com/linyows/dewy/blob/main/cmd/dewy/main.go) and [`cli.go`](https://github.com/linyows/dewy/blob/main/cli.go) to build a `Config`. The `dewy.New` function initializes the core with a file-based cache (`kvs.File`). When `Start` is invoked, it launches the registry client, notifier, and scheduler.

The scheduler triggers `Run` at configured intervals. This method calls `registry.Current` to check for new versions, consults the `KVS` cache to avoid redundant downloads, and uses `artifact.New` to fetch the artifact if needed. After caching via `kvs.ExtractArchive`, it creates a `current` symlink and launches the binary via the `starter` helper, finally sending a deployment report through the notifier.

For **container** deployments, the flow diverges at `RunContainer`. After pulling the OCI image via `artifact.New`, Dewy resolves port mappings through `resolvePortMappings`, which auto-detects exposed ports when not explicitly configured. It then starts containers using the selected runtime (`container.NewDocker` or `container.NewPodman`), registering each with the TCP proxy via `addProxyBackend`.

Once health checks pass, Dewy removes old containers from the proxy and stops them, cleans up obsolete images, and updates the admin API state. Signal handling via `waitSigs` ensures graceful shutdowns, invoking `stopManagedContainers`, `stopProxy`, and `stopAdminAPI` when receiving SIGTERM or SIGINT.

This architecture isolates side effects within dedicated sub-packages while the core focuses on deployment decisions, enabling users to swap registries, caches, or runtimes without modifying the orchestration logic.

## Summary

- **Dewy Core** ([`dewy.go`](https://github.com/linyows/dewy/blob/main/dewy.go)) orchestrates the deployment lifecycle, scheduling, and signal handling for all command types.
- **Registry Interface** ([`registry/registry.go`](https://github.com/linyows/dewy/blob/main/registry/registry.go)) abstracts version sources like GitHub Releases, OCI registries, and S3, enabling pluggable artifact discovery.
- **Artifact & Cache** ([`artifact/artifact.go`](https://github.com/linyows/dewy/blob/main/artifact/artifact.go) and [`kvs/kvs.go`](https://github.com/linyows/dewy/blob/main/kvs/kvs.go)) handle secure downloads and local persistence with support for filesystem, Redis, and Consul backends.
- **Container Runtime** ([`container/docker.go`](https://github.com/linyows/dewy/blob/main/container/docker.go), [`container/podman.go`](https://github.com/linyows/dewy/blob/main/container/podman.go)) provides a unified interface for Docker and Podman operations, supporting zero-downtime rolling updates.
- **Infrastructure Services** include an in-process **TCP Proxy** for traffic routing, an **Admin API** for observability, and a **Notifier** system for deployment alerts.

## Frequently Asked Questions

### What is the role of the Dewy Core in the architecture?

The **Dewy Core** acts as the central orchestrator defined in [`dewy.go`](https://github.com/linyows/dewy/blob/main/dewy.go). It initializes all subsystems including the registry client, cache, and notifier, then manages the deployment loop through methods like `Start`, `Run`, and `RunContainer`. The core handles OS signals for graceful shutdowns and coordinates rolling updates, keeping the main decision logic separate from implementation details like network I/O or container runtime specifics.

### How does Dewy support different container runtimes?

Dewy abstracts container operations through the **Runtime** interface implemented in [`container/docker.go`](https://github.com/linyows/dewy/blob/main/container/docker.go) and [`container/podman.go`](https://github.com/linyows/dewy/blob/main/container/podman.go). This interface standardizes lifecycle methods including `Pull`, `Run`, `Stop`, and health-check polling, allowing the core to treat Docker and Podman identically. Users specify their preferred runtime in the `ContainerConfig`, and Dewy instantiates the appropriate implementation via `container.NewDocker` or `container.NewPodman`, supporting rolling updates with zero downtime regardless of the underlying engine.

### What caching mechanisms does Dewy use for artifacts?

Dewy implements caching through the **KVS** (Key-Value Store) interface defined in [`kvs/kvs.go`](https://github.com/linyows/dewy/blob/main/kvs/kvs.go), supporting multiple persistence backends. The system can store artifacts locally using the `file` backend, maintain ephemeral caches with `memory`, or distribute state using `redis` or `consul`. The cache tracks downloaded artifacts under versioned keys and maintains a `current` reference to the active deployment, enabling atomic rollbacks and preventing redundant network requests when the registry reports a version already present in storage.

### How does Dewy achieve zero-downtime deployments for containers?

Dewy implements zero-downtime rolling updates through a combination of an **in-process TCP reverse proxy** and health-check orchestration. When deploying new container versions, Dewy starts new instances alongside existing ones, registers them with the TCP proxy via `addProxyBackend`, and performs health checks. Once new containers pass validation, Dewy removes old instances from the proxy via `removeBackend` and stops them, ensuring continuous traffic flow without requiring external load balancers.