| title | Configuration |
|---|---|
| description | Configure Decision Engine via config files and environment variable overrides. |
This document explains how to configure Decision Engine for local and on-prem deployments.
config/development.toml: used for host/source runsconfig/docker-configuration.toml: used for Docker and Compose runshelm-charts/config/development.toml: Kubernetes chart template config
These files already exist with all required sections. Edit the one that matches your runtime rather than copying from config.example.toml, which is incomplete.
[server]
host = "0.0.0.0"
port = 8080host is the bind address. Use 0.0.0.0 for Docker/deployed, 127.0.0.1 for local-only.
[log.console]
enabled = true
level = "DEBUG"
log_format = "default"log_format accepts "default" (human-readable) or "json" (structured, recommended for prod).
[log.telemetry]
metrics_enabled = true
ignore_errors = true
otel_exporter_otlp_endpoint = "http://localhost:4317"
otel_exporter_otlp_timeout = 10000 # milliseconds per export requestThere is no metrics port to scrape. When metrics_enabled is on, metrics are pushed over OTLP/gRPC to an OpenTelemetry collector every 3 seconds, the same cadence as Hyperswitch. In the Hyperswitch clusters the collector re-exposes them to vmagent, so they land in VictoriaMetrics and the Grafana VictoriaMetrics datasource. The collector adds source_namespace, source_pod and source_app labels; filter by source_namespace="decision-engine" in Grafana. With metrics_enabled = false the instruments are no-ops.
metrics_enabled defaults to false and the endpoint defaults to the local collector (http://localhost:4317 for a native binary, http://otel-collector:4317 inside Compose), so enabling is a single flag. oneclick.sh starts the collector and Prometheus and runs the API with metrics enabled; the monitoring Compose profile adds Grafana. Metrics are then at http://localhost:9898/metrics on the collector and in Prometheus at http://localhost:9090.
Environment variables follow the usual prefix, e.g. DECISION_ENGINE__LOG__TELEMETRY__METRICS_ENABLED=true and DECISION_ENGINE__LOG__TELEMETRY__OTEL_EXPORTER_OTLP_ENDPOINT=....
[limit]
request_count = 1
duration = 60Controls rate limiting on the delete APIs. request_count requests allowed per duration seconds.
[cache_config]
service_config_redis_prefix = "DE_service_config_"
service_config_ttl = 300 # Redis TTL for service config entries, in secondsMySQL and PostgreSQL use separate config sections.
MySQL:
[database]
username = "db_user"
password = "db_pass"
host = "localhost"
port = 3306
dbname = "decision_engine_db"PostgreSQL:
[pg_database]
pg_username = "db_user"
pg_password = "db_pass"
pg_host = "localhost"
pg_port = 5432
pg_dbname = "decision_engine_db"For Docker Compose runs both are pre-wired via service names in config/docker-configuration.toml.
[tenant_secrets]
public = { schema = "public" }Maps tenant identifiers to database schemas. The shipped config files (config/development.toml, config/docker-configuration.toml) define only the public tenant — add entries for any additional tenant you want to support.
Some routes resolve the tenant from an x-tenant-id request header rather than the authenticated merchant, and reject the request outright if it's missing (TE_03). Send x-tenant-id: public on GET /health/diagnostics, every GET /analytics/* route, and POST /gateway-score/reset — see API Guide.
[redis]
host = "127.0.0.1"
port = 6379Redis is required — it's used for caching routing config and service config. For Docker, use the service name as host.
[user_auth]
jwt_secret = "change_me_in_production_use_32chars!!"
jwt_expiry_seconds = 86400
email_verification_enabled = false
jwt_revocation_cache_ttl_ms = 0Use a strong, random jwt_secret — 32+ characters recommended. Set email_verification_enabled = true if you've wired an email provider.
jwt_revocation_cache_ttl_ms caches "this token is not revoked" in memory, so authenticated
requests skip the JWT denylist read in Redis for that many milliseconds. The cost is that
a logged-out session keeps working until the window expires. Only the confirmed
"not revoked" answer is cached — a denylisted token is refused, and a failed Redis read isn't
stored — so an outage can't extend a revoked session. Token expiry (exp) is unaffected.
0 (the default) reads Redis on every request; 1000 bounds revocation to a second.
[admin_secret]
secret = "test_admin"Used to authenticate the POST /merchant-account/create endpoint (admin bootstrap). Change this in production.
api_key_auth_enabled = trueTop-level flag. When true, protected routes accept x-api-key in addition to JWT bearer tokens. When false, the auth middleware allows all requests through without authentication — this effectively disables auth for every protected route. Do not set this to false in any environment that should enforce auth.
Both Kafka and ClickHouse require enabled = true — without it, analytics is disabled even if the connection details are configured.
[analytics.kafka]
enabled = true
brokers = "localhost:9092"
api_topic = "api"
domain_topic = "domain"
[analytics.clickhouse]
enabled = true
url = "http://localhost:8123"
user = "decision_engine"
password = "decision_engine"Decision outcomes are published to Kafka and consumed into ClickHouse. Both are required for analytics and audit dashboard views. For Docker runs, these are pre-configured and enabled via the Compose profiles.
[tls]
certificate = "cert.pem"
private_key = "key.pem"Paths to PEM-format certificate and key files. Only needed if you're terminating TLS at the app layer rather than a reverse proxy.
[api_client]
client_idle_timeout = 90
pool_max_idle_per_host = 10
identity = ""Controls the outbound HTTP client used for upstream calls. Set identity to a PEM path if you need mTLS.
By default, secrets in config are stored in plaintext. For production, use one of the two supported backends.
Requires the kms-aws feature (included in the release feature set).
[secrets_management]
secrets_manager = "aws_kms"
[secrets_management.aws_kms]
key_id = "your-kms-key-id"
region = "us-east-1"Requires the kms-hashicorp-vault feature.
[secrets_management]
secrets_manager = "hashi_corp_vault"
[secrets_management.hashi_corp_vault]
url = "http://127.0.0.1:8200"
token = "hvs.your_token"When a secrets manager is configured, sensitive fields like database.password and user_auth.jwt_secret are resolved from the vault rather than the config file.
Selected values can be overridden at runtime via environment variables. This is useful in Helm deployments via extraEnvVars. Consult src/config.rs for the full mapping.