Skip to main content
Caddy is built on a powerful, extensible architecture that emphasizes modularity, configuration flexibility, and automatic HTTPS. This page explains how Caddy’s core components work together to deliver a production-ready web server.

Core Architecture

Caddy’s architecture revolves around several key concepts:
1

Config Structure

At the heart of Caddy is the Config struct, which represents the entire configuration:
caddy.go:68-95
The configuration is natively expressed as JSON, but config adapters can convert other formats (like Caddyfile) into Caddy JSON.
2

App Module System

Caddy runs multiple apps, each responsible for a specific area of functionality:
caddy.go:98-101
Common apps include:
  • http - HTTP server and routing
  • tls - Certificate management and TLS configuration
  • pki - Internal PKI for local certificates
  • Custom apps via third-party modules
3

Context and Lifecycle

Each configuration has a Context that manages module lifecycles:
context.go:46-55
The Context ensures proper provisioning, validation, and cleanup of all modules.

Configuration Lifecycle

Understanding the configuration lifecycle helps you debug issues and write better modules.
When Caddy loads a configuration, it follows this precise sequence:

Detailed Flow

From caddy.go:389-468, the run() function orchestrates the entire process:
If any app fails to start, Caddy stops all previously-started apps and cleans up provisioned modules to prevent resource leaks.

Admin API

The Admin API provides runtime control over Caddy’s configuration:
admin.go:67-86

Key Admin Endpoints

The admin API uses ETags for optimistic concurrency control, preventing race conditions during config updates.

Storage System

Caddy uses a pluggable storage system for persisting TLS certificates and other assets:
caddy.go:530-550
The default storage is the file system, but you can use:
  • Consul
  • DynamoDB
  • Redis
  • Custom storage implementations

Event System

Caddy has an event system for monitoring and reacting to changes:
caddy.go:1070-1092
Events are emitted for:
  • Certificate renewals
  • Server starts/stops
  • Config changes
  • Custom module events
Events are experimental and follow the CloudEvents specification for compatibility with external systems.

Configuration Autosave

Caddy automatically persists configurations that are pushed via the API:
caddy.go:362-384
This allows you to resume from the last working configuration after a restart.

Graceful Reloads

One of Caddy’s most powerful features is zero-downtime config reloads:
1

New Config Validation

The new configuration is fully validated before being applied.
2

Atomic Swap

The old and new contexts are swapped atomically:
caddy.go:353-356
3

Graceful Shutdown

The old context is stopped asynchronously, allowing in-flight requests to complete.
If the new config fails to start, Caddy restores the old configuration state to maintain availability.

Instance Identity

Each Caddy instance has a unique UUID stored persistently:
caddy.go:913-932
This UUID is used for:
  • Cluster coordination
  • Storage locking
  • Distributed certificate management

Best Practices

1

Use the Admin API

Prefer using the admin API for config changes rather than restarting the process.
2

Test Configs

Use caddy validate to test configurations before deploying them.
3

Monitor Events

Subscribe to Caddy events to track certificate renewals and config changes.
4

Backup Configs

Regularly backup your configuration and the autosave file.