Skip to main content
The events module is EXPERIMENTAL and subject to change. Pay close attention to release notes when upgrading.
The events module implements a global eventing system within Caddy. Modules can emit and subscribe to events, providing hooks into deep parts of the codebase that aren’t otherwise accessible.

Overview

Module ID: events The events system enables:
  • Event emission - Modules can broadcast events when important actions occur
  • Event subscription - Handlers can react to events from specific modules
  • Event propagation - Events bubble up the module tree (DOM-like)
  • Flow control - Handlers can abort event propagation
  • Metadata passing - Events carry data between emitters and handlers

Event Propagation

Events propagate in a DOM-like fashion:
This allows handlers to:
  • Listen to specific modules
  • Listen to entire namespaces
  • Catch all events globally

Configuration

Basic Structure

Subscriptions

Subscriptions bind handlers to events.
array of strings
Event name(s) to listen for. If empty or omitted, matches all events.Examples:
  • ["cert_obtained"] - Listen for certificate obtained events
  • ["cert_obtained", "cert_renewed"] - Multiple specific events
  • [] - All events
array of module IDs
Module ID(s) or namespaces from which to receive events. If empty or omitted, matches all modules.Examples:
  • ["tls"] - All TLS events
  • ["http.handlers.file_server"] - Specific module
  • ["http.handlers"] - All HTTP handlers
  • [] - All modules
array of objects
required
Event handler modules that execute when events match. At least one handler is required.Handlers are invoked in an arbitrary order.

Subscription Examples

Listen to All TLS Events

Listen to Specific Event from Any Module

Listen to All HTTP Handler Events

Catch-All Subscription

Event Handlers

Event handlers implement the action to take when an event occurs.

Handler Interface

Handlers receive:
  • Context - Request context with cancellation
  • Event - Event data including name, origin, timestamp, and metadata
Handlers can:
  • Read event data
  • Add metadata to the event
  • Return caddy.ErrEventAborted to stop propagation
  • Return other errors (logged but don’t stop propagation)

Event Object

Events contain:
UUID
Unique identifier for this event occurrence
string
Event name (e.g., cert_obtained)
time.Time
When the event was created
Module
The module that emitted the event
map[string]any
Event-specific metadata. Not copied for efficiency; don’t modify in other goroutines after emission.
error
Set to caddy.ErrEventAborted if a handler aborted the event

Event Data in Replacer

Event information is automatically available in the Caddy replacer:
  • {event} - The full event object
  • {event.id} - Event UUID
  • {event.name} - Event name
  • {event.time} - Event timestamp
  • {event.time_unix} - Unix timestamp in milliseconds
  • {event.module} - Origin module ID
  • {event.data} - Full data map
  • {event.data.field_name} - Specific field from event data
Useful in handler configurations:

Aborting Events

Handlers can abort event propagation by returning caddy.ErrEventAborted:
When aborted:
  1. Event propagation stops immediately
  2. Event is marked as aborted
  3. Emitter receives the aborted event
  4. Emitter may choose to adjust program flow
Not all event emitters support aborting. Check module documentation to see if aborting an event affects behavior.

Synchronous Execution

Event handlers are fired synchronously as part of the regular program flow. This means: Benefits:
  • Handlers can control program flow
  • Handlers can add data back to the origin module
  • Predictable execution order (within a subscription level)
⚠️ Cautions:
  • Slow handlers block the emitter
  • Handlers should complete quickly
  • Long-running tasks should spawn goroutines

Handler Ordering

Event handlers are invoked in arbitrary order within each subscription level. Do not rely on handler execution order.
Handlers should:
  • Be independent of each other
  • Not rely on other handlers’ logic
  • Be idempotent when possible

Programmatic Subscriptions

Go code can subscribe to events during provisioning:

On() Method

Syntactic sugar for simple subscriptions:
  • eventName - Event to listen for (empty string = all events)
  • handler - Handler to invoke
  • Listens to events from all modules

Emitting Events

Modules emit events using:

Example Emission

Common Event Names

While event names are module-specific, some common patterns:
  • cert_obtained - Certificate was obtained
  • cert_renewed - Certificate was renewed
  • cert_failed - Certificate operation failed
  • config_loaded - Configuration loaded
  • server_started - Server started
  • server_stopped - Server stopped
  • request_received - HTTP request received
  • response_sent - HTTP response sent
Check specific module documentation for available events.

Use Cases

Certificate Lifecycle Hooks

Logging Events

Webhooks

Metrics Collection

Best Practices

  1. Keep handlers fast - Spawn goroutines for long-running work
  2. Handle errors gracefully - Don’t crash on event handling errors
  3. Be specific - Subscribe to specific events/modules when possible
  4. Don’t modify shared state - Event data map is shared; don’t mutate it
  5. Test abort behavior - Ensure aborting events works as expected
  6. Log appropriately - Use structured logging in handlers

Troubleshooting

Handlers Not Firing

Problem: Event handlers aren’t being invoked Solutions:
  • Verify event name matches exactly
  • Check module ID is correct
  • Ensure subscription is in apps.events.subscriptions
  • Enable debug logging to see event emissions

Event Storms

Problem: Too many events causing performance issues Solutions:
  • Be more specific in subscriptions
  • Add filtering in handlers
  • Avoid emitting events in tight loops

Context Cancellation

Problem: context canceled errors in handlers Solutions:
  • Check for context cancellation in long-running handlers
  • Respect context deadlines
  • Don’t block indefinitely

Security Considerations

  • Handler execution is synchronous - Malicious handlers can block operations
  • Event data is shared - Don’t include secrets in event data
  • Handlers run with Caddy’s privileges - Be cautious with exec handlers
  • No sandboxing - Handlers have full access to Caddy’s internals

Future Development

As an experimental feature, the events module may change significantly. Possible future additions:
  • Asynchronous event handling
  • Event filtering/transformation
  • Event persistence
  • Remote event emission
  • Event replay