Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/cloudflare/pingora/llms.txt

Use this file to discover all available pages before exploring further.

Pingora reads its settings from a YAML file whose path is supplied via the -c / --conf CLI flag. The file is a flat key-value map; unknown keys are silently ignored, which lets you embed your own application settings in the same file. The only required field is version, which must be 1.
Set the RUST_LOG=INFO environment variable when running with error_log configured. Pingora uses the standard log crate, and the log output is only emitted when the log level is enabled.

Minimal Example

---
version: 1

Full Example

---
version: 1
threads: 4
pid_file: /run/pingora.pid
error_log: /var/log/pingora/error.log
upgrade_sock: /tmp/pingora_upgrade.sock
user: nobody
group: webusers

Settings Reference

KeyMeaningType
versionConfiguration file version. Must be 1.number
pid_filePath to the PID file written after daemonization.string
daemonRun the server in the background. Equivalent to the -d CLI flag.bool
error_logPath for error log output. Uses stderr if not set.string
upgrade_sockPath to the Unix socket used for graceful zero-downtime upgrades. Old and new instances must agree on this path.string
threadsNumber of worker threads per service.number
userUnix user to run as after daemonization. Allows the process to start as root, load secrets, then drop privileges.string
groupUnix group to run as after daemonization.string
working_directoryWorking directory for the daemonized process.string
client_bind_to_ipv4Source IPv4 addresses to bind when opening upstream connections.list of string
client_bind_to_ipv6Source IPv6 addresses to bind when opening upstream connections.list of string
ca_filePath to a PEM root CA bundle used when verifying upstream TLS certificates.string
s2n_config_cache_sizeMaximum number of unique s2n TLS configurations to cache. 0 disables the cache. Default: 10. Applies only when using the s2n-tls backend.number
work_stealingEnable the work-stealing Tokio runtime (default true). Disabling this switches to a single-threaded scheduler per service.bool
runtime_enable_alt_timerEnable Tokio’s experimental alternative timer on work-stealing runtimes. Requires building with --cfg tokio_unstable. Ignored when work_stealing is false. Default: false.bool
fast_timeout_to_tokio_threshold_secondsTimeout durations greater than this value delegate to Tokio’s native timeout instead of Pingora’s fast timeout. Default: 900. Set to null to disable the Tokio fallback entirely.number
runtime_metrics_poll_time_histogramEnable Tokio poll-time histograms on service runtimes. Requires --cfg tokio_unstable. Adds two timestamp reads to every task poll. Default: false.bool
runtime_metrics_poll_time_histogram_scaleBucket scale for poll-time histograms. Valid values: linear, log. Ignored unless runtime_metrics_poll_time_histogram is enabled.string
runtime_metrics_poll_time_histogram_resolution_microsWidth of the first histogram bucket in microseconds. Must be greater than 0. Ignored unless runtime_metrics_poll_time_histogram is enabled.number
runtime_metrics_poll_time_histogram_bucketsNumber of histogram buckets. Must be between 1 and 1024. Memory usage scales with runtimes × workers × buckets. Ignored unless runtime_metrics_poll_time_histogram is enabled.number
upstream_keepalive_pool_sizeNumber of idle upstream connections to keep per Tokio worker. Effective ceiling is upstream_keepalive_pool_size × threads. Eviction is globally consistent across workers.number
daemon_wait_for_readyWhen true and daemon is true, the parent process waits for the daemon to send SIGUSR1 before exiting. This causes systemd to delay sending SIGQUIT to the old process until the new instance is fully bootstrapped. Default: false.bool
daemon_ready_timeout_secondsHow long (in seconds) the parent waits for the daemon’s SIGUSR1 readiness signal. If the daemon does not signal in time, the parent exits with a non-zero code, causing systemd to abort the reload. Default: 600.number
daemon_notify_timeout_secondsHow long (in seconds) the daemon retries sending SIGUSR1 to the parent when the attempt fails with a permission error. This covers the brief window after the fork where the parent has not yet dropped its UID to match the daemon. Default: 60.number

Extension

Any key that Pingora does not recognise is silently ignored. This lets you add your own application-specific settings to the same YAML file and read them using a custom deserialization step — without needing a separate config file.

dial9 Runtime Telemetry

dial9 Tokio runtime telemetry is configured programmatically, not through the YAML file. This design avoids accidentally enabling experimental telemetry on every service runtime and allows services to supply non-serializable values such as a pre-built S3 client. dial9 is only available when Pingora is compiled with the dial9 feature flag and --cfg tokio_unstable. Individual services can override the global runtime options by implementing runtime_opts_override():
use pingora::server::{Dial9RuntimeOpts, RuntimeOpts};
use pingora::services::Service;

struct MyService;

impl Service for MyService {
    fn name(&self) -> &str {
        "my-service"
    }

    fn runtime_opts_override(&self, global: &RuntimeOpts) -> Option<RuntimeOpts> {
        let mut opts = global.clone();
        opts.dial9 = Some(
            Dial9RuntimeOpts::new("/var/lib/pingora/dial9/my-service/trace.bin")
                .with_max_file_size(100 * 1024 * 1024)
                .with_max_total_size(512 * 1024 * 1024),
        );
        Some(opts)
    }
}
When built with the additional dial9-worker-s3 feature, sealed trace segments can also be uploaded to an S3-compatible bucket. The S3 client is optional — when omitted, dial9 uses the AWS SDK default configuration chain and its bucket-region detection:
use pingora::server::{Dial9RuntimeOpts, Dial9S3UploadOpts, RuntimeOpts};
use pingora::services::Service;

struct MyService {
    s3_client: aws_sdk_s3::Client,
}

impl Service for MyService {
    fn name(&self) -> &str {
        "my-service"
    }

    fn runtime_opts_override(&self, global: &RuntimeOpts) -> Option<RuntimeOpts> {
        let mut opts = global.clone();
        opts.dial9 = Some(
            Dial9RuntimeOpts::new("/var/lib/pingora/dial9/my-service/trace.bin")
                .with_s3_upload(
                    Dial9S3UploadOpts::new("my-trace-bucket", "my-service")
                        .with_prefix("traces/my-service")
                        .with_region("us-east-1")
                        .with_client(self.s3_client.clone()),
                ),
        );
        Some(opts)
    }
}

Build docs developers (and LLMs) love