Open-Source Wikis

/

Traefik

/

Traefik

/

Architecture

traefik/traefik

Architecture

Traefik is a single Go process. The interesting structure is internal: how a configuration change in your orchestrator becomes a routed request without restarting the binary.

This page walks through the main pieces and how they connect. Subsystem pages under Systems drill into each box.

Bird's-eye view

graph LR
    subgraph External["External sources"]
        K8s[Kubernetes API]
        Docker[Docker / Swarm]
        FileSrc[File / KV store]
        ACME[Let's Encrypt]
    end

    subgraph Traefik["Traefik process"]
        Providers[Providers<br/>pkg/provider/*]
        Aggregator[Provider aggregator<br/>pkg/provider/aggregator]
        Watcher[Configuration watcher<br/>pkg/server/configurationwatcher.go]
        Factory[Router factory<br/>pkg/server/routerfactory.go]
        EPs[Entry points<br/>pkg/server/server_entrypoint_*.go]
        Routers[Routers + Middlewares + Services]
    end

    Client((HTTP/TCP/UDP<br/>client))
    Backends((Upstream<br/>services))

    K8s --> Providers
    Docker --> Providers
    FileSrc --> Providers
    Providers --> Aggregator
    Aggregator -->|dynamic.Message| Watcher
    Watcher -->|dynamic.Configurations| Factory
    Factory -->|swap handler tree| EPs
    Client -->|TCP/UDP/QUIC| EPs
    EPs --> Routers
    Routers -->|HTTP| Backends
    ACME -.->|certificates| Routers

Static vs dynamic configuration

Traefik distinguishes two kinds of configuration. They live in different packages and have different lifecycles.

Aspect Static configuration Dynamic configuration
Schema pkg/config/static/static_config.go pkg/config/dynamic/http_config.go, tcp_config.go, udp_config.go, middlewares.go
Source traefik.yml / traefik.toml, CLI flags, env vars Providers (Docker, Kubernetes, file watcher, KV stores, REST API, …)
When loaded At startup. Most fields cannot change without a restart. Continuously. Changes are applied without restarting.
Examples Entry points, providers, certificate resolvers, log/tracing/metrics, API/dashboard Routers, services, middlewares, TLS certificates, TLS options

The distinction matters because most of the runtime — including the router tree, certificates, and middleware chains — is rebuilt every time the dynamic config changes.

Process startup

cmd/traefik/traefik.go does the actual wiring. Roughly:

  1. Build the static.Configuration from the loaders chained in traefik.go (DeprecationLoader, FileLoader, FlagLoader, EnvLoader — all from github.com/traefik/paerser).
  2. Validate it (SetEffectiveConfiguration + ValidateConfiguration).
  3. Start observability: structured logger via pkg/observability/logs, metrics registries via pkg/observability/metrics, OpenTelemetry tracing via pkg/observability/tracing.
  4. Construct providers from the static config, wrap them in the aggregator (pkg/provider/aggregator).
  5. Build a ConfigurationWatcher (pkg/server/configurationwatcher.go) and register listeners that update the live router tree.
  6. Build TCP/UDP entry points (pkg/server/server_entrypoint_tcp.go, server_entrypoint_udp.go).
  7. Start the Server (pkg/server/server.go), which calls Start on entry points and the watcher.

Configuration application loop

The interesting concurrent code is in pkg/server/configurationwatcher.go. It runs three goroutines:

  1. The provider aggregator pushes dynamic.Message{ProviderName, Configuration} onto an internal channel.
  2. receiveConfigurations deduplicates messages per provider, applies registered transformers (middleware plugins, hub, etc.), and pushes the merged snapshot onto another channel.
  3. applyConfigurations reads the latest snapshot and calls each registered listener — typically the router factory, which rebuilds and atomically swaps the entry points' handler trees.
sequenceDiagram
    participant P as Provider
    participant A as Aggregator
    participant W as Watcher
    participant F as RouterFactory
    participant E as EntryPoint

    P->>A: dynamic.Message
    A->>W: dynamic.Message
    W->>W: deduplicate per provider
    W->>W: run transformers
    W->>F: dynamic.Configurations (merged)
    F->>F: build router tree<br/>(routers + middlewares + services)
    F->>E: SwitchRouter(new tree)
    Note over E: Subsequent connections use<br/>the new handler tree.

The atomic swap is what allows zero-restart configuration changes.

Request lifecycle

Once configuration is applied, an inbound request goes through this chain:

graph TD
    Conn[TCP/UDP connection] --> EP[Entry point listener<br/>pkg/server/server_entrypoint_tcp.go]
    EP -->|HTTP/HTTPS/HTTP3| Mux[HTTP muxer<br/>pkg/muxer/http]
    EP -->|raw TCP| TCPMux[TCP muxer<br/>pkg/muxer/tcp]
    EP -->|UDP| UDPHandler[UDP handler<br/>pkg/server/router/udp]
    Mux --> Router[matched router]
    Router --> Chain[middleware chain<br/>pkg/server/middleware/middlewares.go]
    Chain --> Svc[service<br/>pkg/server/service/service.go]
    Svc --> LB[load balancer<br/>pkg/server/service/loadbalancer/*]
    LB --> RT[smart round-tripper<br/>pkg/proxy/* + pkg/server/service/transport.go]
    RT --> Backend[(upstream)]

Some details worth knowing:

  • The HTTP muxer is implemented in pkg/muxer/http; it speaks Traefik's rule language (Host(...) && PathPrefix(...)) parsed by pkg/rules/parser.go.
  • The TCP muxer (pkg/muxer/tcp) sniffs ALPN and SNI to multiplex TLS, HTTP, and raw TCP on the same port.
  • pkg/proxy/fast is the high-performance HTTP/1.x reverse proxy. pkg/proxy/httputil is the standard-library variant. pkg/proxy/smart_builder.go chooses between them.
  • TLS certificates and ALPN are handled by pkg/tls/tlsmanager.go, which also serves ACME-resolved certificates from pkg/provider/acme.

Observability is built in

Logs, metrics, and traces are not bolt-ons. The middleware chain is constructed by pkg/server/middleware/middlewares.go and pkg/server/middleware/observability.go, which automatically wrap user-defined middlewares with:

  • An access log middleware (pkg/middlewares/accesslog).
  • A capture middleware (pkg/middlewares/capture) that records latency, status, and byte counts.
  • A metrics middleware (pkg/middlewares/metrics) feeding Prometheus, OTLP, Datadog, StatsD, or InfluxDB exporters.
  • A tracing middleware (pkg/middlewares/observability) using OpenTelemetry.

See Observability for the runtime wiring.

Dashboard and API

The bundled web UI (webui/, Vue 3 + Vite + TypeScript) is compiled to static assets and embedded into the Go binary via webui/embed.go. The HTTP API that the dashboard consumes is implemented under pkg/api/ — see API.

Entry points for modification

  • Adding a new provider: implement provider.Provider in pkg/provider/<name> and wire it in pkg/config/static/static_config.go and pkg/provider/aggregator/aggregator.go.
  • Adding a new middleware: implement http.Handler factory in pkg/middlewares/<name> and register it in pkg/server/middleware/middlewares.go plus the dynamic config schema in pkg/config/dynamic/middlewares.go.
  • Adding a new load-balancing strategy: see pkg/server/service/loadbalancer/ for existing implementations (wrr, p2c, hrw, failover, mirror, leasttime).

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Architecture – Traefik wiki | Factory