> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Environment variables

> Reference the environment variables that configure Matcher, grouped as the code groups them, with each default and the startup checks Matcher applies.

This reference lists the environment variables that configure **Matcher**, the reconciliation engine. Lerian sets these values when it installs or upgrades Matcher. Use this page to find what a setting does, its default, and what Matcher checks at startup.

When a required variable is absent or invalid, Matcher does not start. With `ENV_NAME=production`, Matcher applies extra checks. The **Required** column names each one as "Production".

Some variables only set the starting value of a runtime document. Lerian can change those documents on a running Matcher through [Systemplane](https://docs.lerian.studio/en/reference/platform/systemplane/overview.md). The [runtime documents](#runtime-documents) section lists them.

## Application

| Variable | Description | Default | Required |
| - | - | - | - |
| `ENV_NAME` | Environment name. With `production`, Matcher turns off Swagger and refuses an insecure object storage endpoint. It also applies the checks marked "Production" on this page. | `development` | No |
| `LOG_LEVEL` | Log level: `debug`, `info`, `warn`, `error`, or `fatal`. Any other value stops the startup. | `info` | No |
| `DEPLOYMENT_MODE` | Deployment model: `saas`, `byoc`, or `local`, in any letter case. With `saas` or `byoc`, Matcher requires `IDEMPOTENCY_HMAC_SECRET`, refuses an `http` value in `PUBLIC_BASE_SCHEMES`, and refuses a malformed `PUBLIC_BASE_HOST`. The `/readyz` response also reports the value. | — | Yes |
| `SHUTDOWN_GRACE_PERIOD_SEC` | Seconds Matcher waits for work in progress to finish when it stops. | `12` | No |
| `ALLOW_INSECURE_TLS` | Allows PostgreSQL, Redis, and RabbitMQ connections without TLS. Without `true`, Matcher refuses those connections. The defaults on this page do not use TLS. | — | No |

## HTTP server

| Variable | Description | Default | Required |
| - | - | - | - |
| `SERVER_ADDRESS` | API bind address. | `:4018` | No |
| `HTTP_READ_TIMEOUT` | Maximum time to read one request, as a duration such as `15m`. It also covers streamed file uploads. | `15m` | No |
| `HTTP_BODY_LIMIT_BYTES` | Maximum body size, in bytes, for routes that buffer the whole request. | `104857600` | No |
| `CORS_ALLOWED_ORIGINS` | Allowed CORS origins (CSV). | `http://localhost:3000` | Production: at least one origin, and not `*` |
| `CORS_ALLOWED_METHODS` | Allowed CORS methods (CSV). | `GET,POST,PUT,PATCH,DELETE,OPTIONS` | No |
| `CORS_ALLOWED_HEADERS` | Allowed CORS headers (CSV). | `Origin,Content-Type,Accept,Authorization,X-Request-ID` | No |
| `SERVER_TLS_CERT_FILE` | Path to the TLS certificate. Set it together with `SERVER_TLS_KEY_FILE`. A certificate turns on HSTS. | — | No |
| `SERVER_TLS_KEY_FILE` | Path to the TLS private key. Set it together with `SERVER_TLS_CERT_FILE`. | — | No |
| `TLS_TERMINATED_UPSTREAM` | Set to `true` when a load balancer terminates TLS in front of Matcher. It turns on HSTS. | `false` | No |
| `TRUSTED_PROXIES` | Trusted proxy CIDRs (CSV) for client IP resolution. Matcher refuses `*`, `0.0.0.0/0`, and `::/0`. | — | Production |
| `PUBLIC_BASE_HOST` | Public `host[:port]` that Matcher puts in the webhook and callback URLs it issues. Use the bare host, without a scheme or path. When empty, Matcher uses `SERVER_ADDRESS`. | — | No |
| `PUBLIC_BASE_SCHEMES` | Scheme for those public URLs. | `https` | No |
| `SWAGGER_ENABLED` | Serves the Swagger UI. `ENV_NAME=production` turns it off. | `false` | No |

## Authentication

| Variable | Description | Default | Required |
| - | - | - | - |
| `PLUGIN_AUTH_ENABLED` | Turns on Access Manager authentication. Matcher also accepts the older name `AUTH_ENABLED`. When both names are set to different values, Matcher refuses to start. | `false` | No |
| `PLUGIN_AUTH_ADDRESS` | Access Manager address. Matcher also accepts the older name `AUTH_SERVICE_ADDRESS`, with the same conflict rule. | — | When the provider is `plugin-auth` |
| `AUTH_PROVIDER` | Authentication provider: `plugin-auth` or `disabled`. When unset, `PLUGIN_AUTH_ENABLED` selects it. An explicit value wins. Any other value stops the startup. | — | No |
| `AUTH_REQUIRED` | With `true` and authentication off, each `/v1` operation that needs a permission answers `503`. | `false` | No |
| `AUTH_PRINCIPAL_REQUIRED_WHEN_DISABLED` | With `true` and authentication off, each `/v1` operation that needs a permission still requires a bearer token and answers `401` without one. Matcher does not call Access Manager for these requests. Without `AUTH_JWT_VERIFY_CERT` or `AUTH_JWT_VERIFY_CERT_PATH`, Matcher does not check the token signature. | `false` | No |
| `AUTH_M2M_PRODUCT_FORWARD_ENABLED` | With `true`, Matcher also sends its product name to Access Manager when it checks an application token. | `false` | No |
| `AUTH_TIMEOUT` | Time limit for the Access Manager check of one request, retries included, as a duration such as `5s`. | `30s` | No |
| `AUTH_CACHE_TTL` | Time that Matcher keeps each Access Manager decision, as a duration such as `60s`. A permission change can take this long to apply. When unset, Matcher keeps no decisions. | — | No |
| `AUTH_BREAKER_ENABLED` | Turns on a circuit breaker for Access Manager calls. After 5 failed calls in a row, it stops the calls for 30 seconds. Meanwhile, Matcher refuses each request that has no cached approval. | `false` | No |
| `AUTH_RETRY_MAX` | Maximum retries of an Access Manager call that fails without a decision. `0` turns off retries. | `0` | No |
| `AUTH_JWT_VERIFY_CERT` | One or more PEM RSA public keys or X.509 certificates, separated by newlines. With a loaded key, Matcher checks the RS256 signature and the expiry of each bearer token, and answers `401` when the check fails. It takes precedence over `AUTH_JWT_VERIFY_CERT_PATH`. | — | No |
| `AUTH_JWT_VERIFY_CERT_PATH` | Path to a file with the same content. Matcher reads it only when `AUTH_JWT_VERIFY_CERT` is empty. | — | No |
| `AUTH_JWT_ISSUER` | With a loaded key, Matcher answers `401` to a token whose `iss` claim differs from this value. | — | No |

## Tenancy

| Variable | Description | Default | Required |
| - | - | - | - |
| `DEFAULT_TENANT_ID` | Tenant ID for single-tenant mode. It must be a UUID. | `11111111-1111-1111-1111-111111111111` | No |
| `DEFAULT_TENANT_SLUG` | Tenant slug for single-tenant mode. | `default` | No |
| `MULTI_TENANT_ENABLED` | Turns on multi-tenant mode through Tenant Manager. It requires the `plugin-auth` provider, an environment of `staging` or `production`, `MULTI_TENANT_URL`, and `MULTI_TENANT_SERVICE_API_KEY`. | `false` | No |
| `ENVIRONMENT_NAME` | Environment name that multi-tenant mode checks. When unset, Matcher uses `ENV_NAME`. | — | No |
| `MULTI_TENANT_URL` | Tenant Manager origin: `http` or `https`, with no path and no user information. | — | Multi-tenant mode. Production: `https` |
| `MULTI_TENANT_SERVICE_API_KEY` | API key that Matcher sends to Tenant Manager. Sensitive. | — | Multi-tenant mode |
| `MULTI_TENANT_ENVIRONMENT` | Multi-tenant environment name. When unset, Matcher uses `ENV_NAME`. Multi-tenant mode needs one of the two. | — | No |
| `MULTI_TENANT_ALLOW_INSECURE_HTTP` | Allows an `http` Tenant Manager origin. | `false` | No |
| `MULTI_TENANT_REDIS_HOST` | Redis host that carries tenant lifecycle events. | — | No |
| `MULTI_TENANT_REDIS_PORT` | Port of that Redis. | `6379` | No |
| `MULTI_TENANT_REDIS_PASSWORD` | Password for that Redis. Sensitive. | — | No |
| `MULTI_TENANT_REDIS_TLS` | Uses TLS for that Redis. | `false` | No |
| `MULTI_TENANT_MAX_TENANT_POOLS` | Maximum number of tenant connection pools that Matcher keeps open. | `100` | No |
| `MULTI_TENANT_IDLE_TIMEOUT_SEC` | Seconds before Matcher closes an idle tenant pool. | `300` | No |
| `MULTI_TENANT_TIMEOUT` | Timeout, in seconds, for a Tenant Manager call. | `30` | No |
| `MULTI_TENANT_CIRCUIT_BREAKER_THRESHOLD` | Failed Tenant Manager calls before the circuit breaker opens. | `5` | No |
| `MULTI_TENANT_CIRCUIT_BREAKER_TIMEOUT_SEC` | Seconds the circuit breaker stays open. | `30` | No |
| `MULTI_TENANT_CACHE_TTL_SEC` | Seconds Matcher caches a tenant's configuration. | `120` | No |
| `MULTI_TENANT_CONNECTIONS_CHECK_INTERVAL_SEC` | Seconds between checks of tenant connection settings. | `30` | No |
| `MULTI_TENANT_MAX_OPEN_CONNS_PER_TENANT` | Open connections per tenant database. The value is both the default and the ceiling. `0` keeps the library defaults. | `0` | No |
| `MULTI_TENANT_MAX_IDLE_CONNS_PER_TENANT` | Idle connections per tenant database, with the same rule. | `0` | No |

## PostgreSQL

| Variable | Description | Default | Required |
| - | - | - | - |
| `POSTGRES_HOST` | Primary database host. | `localhost` | No |
| `POSTGRES_PORT` | Primary database port. | `5432` | No |
| `POSTGRES_USER` | Primary database user. | `matcher` | No |
| `POSTGRES_PASSWORD` | Primary database password. Sensitive. The default is a development value. | Development value | Production: not empty and not a development value |
| `POSTGRES_DB` | Database name. | `matcher` | No |
| `POSTGRES_SSLMODE` | PostgreSQL `sslmode`. | `disable` | No |
| `POSTGRES_TLS_REQUIRED` | Refuses to start when `POSTGRES_SSLMODE` is `disable`. | `false` | No |
| `POSTGRES_REPLICA_HOST` | Read replica host. Without it, Matcher ignores the other replica variables. | — | No |
| `POSTGRES_REPLICA_PORT`, `POSTGRES_REPLICA_USER`, `POSTGRES_REPLICA_PASSWORD`, `POSTGRES_REPLICA_DB`, `POSTGRES_REPLICA_SSLMODE` | Read replica connection. Each one falls back to the primary value. The password is sensitive. | Primary value | No |
| `POSTGRES_REPLICA_TLS_REQUIRED` | Same rule as `POSTGRES_TLS_REQUIRED`, for the replica. | `false` | No |
| `POSTGRES_MAX_OPEN_CONNS` | Maximum open connections. | `25` | No |
| `POSTGRES_MAX_IDLE_CONNS` | Maximum idle connections. | `5` | No |
| `POSTGRES_CONN_MAX_LIFETIME_MINS` | Minutes before Matcher replaces a connection. | `30` | No |
| `POSTGRES_CONN_MAX_IDLE_TIME_MINS` | Minutes before Matcher closes an idle connection. | `5` | No |
| `POSTGRES_CONNECT_TIMEOUT_SEC` | Connection timeout, in seconds. | `10` | No |
| `POSTGRES_QUERY_TIMEOUT_SEC` | Query timeout, in seconds. `0` uses the default. | `30` | No |
| `SYSTEMPLANE_POSTGRES_DSN` | Connection string for the Systemplane store. When unset, Matcher builds it from the primary connection. Sensitive. | — | No |

## Redis

| Variable | Description | Default | Required |
| - | - | - | - |
| `REDIS_HOST` | Redis address. One address selects standalone mode. A CSV list selects Cluster mode. With `REDIS_MASTER_NAME`, the list names Sentinel nodes. | `localhost:6379` | No |
| `REDIS_MASTER_NAME` | Sentinel master name. | — | No |
| `REDIS_PASSWORD` | Redis password. Sensitive. | — | Production |
| `REDIS_DB` | Redis database number. | `0` | No |
| `REDIS_TLS` | Uses TLS for Redis. | `false` | No |
| `REDIS_TLS_REQUIRED` | Refuses to start when `REDIS_TLS` is `false`. | `false` | No |
| `REDIS_CA_CERT` | CA certificate for Redis TLS. | — | No |
| `REDIS_POOL_SIZE` | Connection pool size. | `10` | No |
| `REDIS_MIN_IDLE_CONNS` | Minimum idle connections. | `2` | No |
| `REDIS_READ_TIMEOUT_MS` | Read timeout, in milliseconds. | `3000` | No |
| `REDIS_WRITE_TIMEOUT_MS` | Write timeout, in milliseconds. | `3000` | No |
| `REDIS_DIAL_TIMEOUT_MS` | Dial timeout, in milliseconds. | `5000` | No |

## RabbitMQ

| Variable | Description | Default | Required |
| - | - | - | - |
| `RABBITMQ_URI` | Connection scheme: `amqp` or `amqps`. | `amqp` | No |
| `RABBITMQ_HOST` | Broker host. | `localhost` | No |
| `RABBITMQ_PORT` | Broker port. | `5672` | No |
| `RABBITMQ_USER` | Broker user. | `matcher_admin` | Production: not `guest` |
| `RABBITMQ_PASSWORD` | Broker password. Sensitive. The default is a development value. | Development value | Production: not `guest` and not a development value |
| `RABBITMQ_VHOST` | Virtual host. | `/` | No |
| `RABBITMQ_HEALTH_URL` | Management API URL for the health check. | `http://localhost:15672` | No |
| `RABBITMQ_ALLOW_INSECURE_HEALTH_CHECK` | Allows an `http` health check URL. | `false` | Production: `false` |
| `RABBITMQ_TLS_REQUIRED` | Refuses to start when `RABBITMQ_URI` is not `amqps`. | `false` | No |

## Object storage

Matcher writes export files to this S3-compatible storage.

| Variable | Description | Default | Required |
| - | - | - | - |
| `OBJECT_STORAGE_ENDPOINT` | Storage endpoint URL. | `http://localhost:8333` | When the export or cleanup worker is on. Production: `https` |
| `OBJECT_STORAGE_REGION` | Storage region. | `us-east-1` | No |
| `OBJECT_STORAGE_BUCKET` | Bucket for export files. | `matcher-exports` | When the export or cleanup worker is on |
| `OBJECT_STORAGE_ACCESS_KEY_ID` | Static access key ID. Without both static keys, Matcher uses the AWS default credential chain. | — | No |
| `OBJECT_STORAGE_SECRET_ACCESS_KEY` | Static secret access key. Sensitive. | — | No |
| `OBJECT_STORAGE_USE_PATH_STYLE` | Uses path-style bucket addresses. | `true` | No |
| `OBJECT_STORAGE_ALLOW_INSECURE_ENDPOINT` | Allows an `http` endpoint. Matcher accepts `true` only when `ENV_NAME` is `development`, `dev`, `local`, or `test`. | `false` | No |
| `OBJECT_STORAGE_TLS_REQUIRED` | Refuses to start when the endpoint is not `https`. | `false` | No |

## Infrastructure timeouts

| Variable | Description | Default | Required |
| - | - | - | - |
| `INFRA_CONNECT_TIMEOUT_SEC` | Total seconds that Matcher allows for its dependency connections at startup. The value must be at least `1`, and Matcher caps it at `300`. | `30` | No |
| `HEALTH_CHECK_TIMEOUT_MS` | Timeout, in milliseconds, for each readiness check. It wins over `HEALTH_CHECK_TIMEOUT_SEC`. | `800` | No |
| `HEALTH_CHECK_TIMEOUT_SEC` | Timeout, in seconds, for each readiness check. Matcher uses it only when `HEALTH_CHECK_TIMEOUT_MS` is `0`. | `5` | No |

## Telemetry

| Variable | Description | Default | Required |
| - | - | - | - |
| `ENABLE_TELEMETRY` | Turns on OpenTelemetry export. | `false` | No |
| `OTEL_RESOURCE_SERVICE_NAME` | Service name on telemetry. | `matcher` | No |
| `OTEL_LIBRARY_NAME` | Instrumentation library name. | `github.com/LerianStudio/matcher` | No |
| `OTEL_RESOURCE_SERVICE_VERSION` | Service version on telemetry. | `1.1.0` | No |
| `OTEL_RESOURCE_DEPLOYMENT_ENVIRONMENT` | Deployment environment on telemetry. With telemetry on, it must be `development`, `staging`, or `production`. | `development` | No |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP collector endpoint. | `localhost:4317` | No |
| `OTEL_TRACES_SAMPLER` | Trace sampler, read by the OpenTelemetry SDK. | `parentbased_always_on` | No |
| `OTEL_TRACES_SAMPLER_ARG` | Sampler argument, such as a ratio. | — | No |
| `ALLOW_INSECURE_OTEL` | Allows a plaintext collector endpoint when the deployment environment is `production`. Without it, Matcher runs without telemetry in that case. | — | No |
| `DB_METRICS_INTERVAL_SEC` | Seconds between database pool metric samples. | `15` | No |

## Rate limits

Each limit is a maximum number of requests per window. A maximum must be between `1` and `1000000`. A window must be between `1` and `86400` seconds.

| Variable | Description | Default | Required |
| - | - | - | - |
| `RATE_LIMIT_ENABLED` | Turns on the limits in this section. When it is unset or `false`, Matcher applies none of them, whatever the `rate_limit` runtime document holds. | `false` | No |
| `ALLOW_RATELIMIT_FAIL_OPEN` | Behavior when Matcher cannot update a limit counter in Redis. With `true`, the request continues without a limit. With `false`, Matcher answers `503`. | `false` | No |
| `RATE_LIMIT_REDIS_TIMEOUT_MS` | Milliseconds one counter update in Redis can take before the request stops waiting for it. | `500` | No |
| `RATE_LIMIT_MAX` | General API limit. | `100` | No |
| `RATE_LIMIT_EXPIRY_SEC` | General API window, in seconds. | `60` | No |
| `EXPORT_RATE_LIMIT_MAX` | Limit for export requests. | `10` | No |
| `EXPORT_RATE_LIMIT_EXPIRY_SEC` | Export window, in seconds. | `60` | No |
| `DISPATCH_RATE_LIMIT_MAX` | Limit for exception dispatch requests. | `50` | No |
| `DISPATCH_RATE_LIMIT_EXPIRY_SEC` | Dispatch window, in seconds. | `60` | No |
| `ADMIN_RATE_LIMIT_MAX` | Limit for the `/system` admin routes. | `30` | No |
| `ADMIN_RATE_LIMIT_EXPIRY_SEC` | Admin window, in seconds. | `60` | No |

## Idempotency

| Variable | Description | Default | Required |
| - | - | - | - |
| `IDEMPOTENCY_HMAC_SECRET` | Secret that keys the idempotency records. It must be at least 32 bytes in every mode. A new secret makes earlier cached replays unavailable. Sensitive. | — | `saas`, `byoc` |
| `IDEMPOTENCY_RETIRED_HMAC_SECRET` | Secret of the previous release. Set it when you change `IDEMPOTENCY_HMAC_SECRET` while the cutover bridge is on. Sensitive. | — | No |
| `IDEMPOTENCY_CUTOVER_BRIDGE` | Also reads the idempotency records of the previous release, so that a retry across an upgrade does not run twice. | `true` | No |
| `IDEMPOTENCY_RETRY_WINDOW_SEC` | Seconds before a failed request can run again with the same key. | `300` | No |
| `IDEMPOTENCY_SUCCESS_TTL_HOURS` | Hours Matcher keeps a successful response for replay. | `168` | No |

## Outbox

| Variable | Description | Default | Required |
| - | - | - | - |
| `OUTBOX_DISPATCH_INTERVAL_SEC` | Seconds between outbox dispatch runs. | `2` | No |
| `OUTBOX_RETRY_WINDOW_SEC` | Seconds before Matcher retries a failed outbox event. | `300` | No |

## Ingestion

| Variable | Description | Default | Required |
| - | - | - | - |
| `INGESTION_MAX_UPLOAD_BYTES` | Maximum upload size, in bytes. The limit applies to the whole multipart body. | `1073741824` | No |
| `DEDUPE_TTL_SEC` | Seconds Matcher keeps a duplicate-detection key in Redis. | `3600` | No |

## Matching

| Variable | Description | Default | Required |
| - | - | - | - |
| `MATCH_RUN_WORKER_ENABLED` | Runs the worker that executes match runs. | `true` | No |
| `MATCH_RUN_WORKER_POLL_INTERVAL_SEC` | Seconds between polls for new match runs. | `3` | No |
| `MATCHING_CANDIDATE_BATCH_SIZE` | Candidates per matching batch. Matcher caps it at `100000`. | `10000` | No |
| `SCHEDULER_INTERVAL_SEC` | Seconds between checks for due schedules. | `60` | No |
| `BINDING_SCHEDULER_ENABLED` | Runs scheduled pulls from bound sources. | `false` | No |
| `BINDING_SCHEDULER_INTERVAL_SEC` | Seconds between checks for due pulls. | `60` | No |

## Exceptions and webhooks

| Variable | Description | Default | Required |
| - | - | - | - |
| `EXCEPTION_DISPUTE_LOCK_TIMEOUT_MS` | Milliseconds Matcher waits for the lock on a dispute. | `2000` | No |
| `WEBHOOK_TIMEOUT_SEC` | Default timeout, in seconds, for an outbound webhook call. Matcher caps it at `300`. | `30` | No |
| `CALLBACK_RATE_LIMIT_PER_MIN` | Callbacks per minute that Matcher accepts from one external system. | `60` | No |

## Export and cleanup

| Variable | Description | Default | Required |
| - | - | - | - |
| `EXPORT_WORKER_ENABLED` | Runs the worker that writes export files. | `true` | No |
| `EXPORT_WORKER_POLL_INTERVAL_SEC` | Seconds between polls for new export jobs. | `5` | No |
| `EXPORT_WORKER_PAGE_SIZE` | Rows per export page. | `1000` | No |
| `EXPORT_PRESIGN_EXPIRY_SEC` | Seconds a download link for an export stays valid. Matcher caps it at `604800`. | `3600` | No |
| `CLEANUP_WORKER_ENABLED` | Runs the worker that removes expired export files. | `true` | No |
| `CLEANUP_WORKER_INTERVAL_SEC` | Seconds between cleanup runs. | `3600` | No |
| `CLEANUP_WORKER_BATCH_SIZE` | Files per cleanup batch. | `100` | No |
| `CLEANUP_WORKER_GRACE_PERIOD_SEC` | Seconds after expiry before cleanup removes a file. | `3600` | No |

## Archival

| Variable | Description | Default | Required |
| - | - | - | - |
| `ARCHIVAL_WORKER_ENABLED` | Runs the worker that archives old audit log partitions. | `false` | No |
| `ARCHIVAL_WORKER_INTERVAL_HOURS` | Hours between archival runs. | `24` | No |
| `ARCHIVAL_HOT_RETENTION_DAYS` | Hot retention, in days. | `90` | No |
| `ARCHIVAL_WARM_RETENTION_MONTHS` | Months before a partition moves to cold archive storage. With the worker on, it must be greater than the hot retention divided by 30. | `24` | No |
| `ARCHIVAL_COLD_RETENTION_MONTHS` | Cold retention, in months. With the worker on, it must be at least the warm retention. | `84` | No |
| `ARCHIVAL_BATCH_SIZE` | Rows per archival batch. | `5000` | No |
| `ARCHIVAL_STORAGE_BUCKET` | Bucket for archive files. | `matcher-archives` | When the archival worker is on |
| `ARCHIVAL_STORAGE_CLASS` | Storage class: `STANDARD`, `STANDARD_IA`, `ONEZONE_IA`, `INTELLIGENT_TIERING`, `GLACIER_IR`, `GLACIER`, or `DEEP_ARCHIVE`. | `GLACIER` | No |
| `ARCHIVAL_PARTITION_LOOKAHEAD` | Future monthly partitions that Matcher creates ahead of time. | `3` | No |
| `ARCHIVAL_PRESIGN_EXPIRY_SEC` | Seconds a download link for an archive file stays valid. | `3600` | No |

With the archival worker on, the hot retention, batch size, and lookahead must each be at least `1`.

## Governance

| Variable | Description | Default | Required |
| - | - | - | - |
| `ACTOR_PII_ENCRYPTION_KEY` | Key that encrypts actor names and email addresses. Standard base64 of exactly 32 bytes. When `ENV_NAME` is not `development`, `dev`, `local`, or `test`, actor mappings need it. Sensitive. | — | No |

## Extraction engine

| Variable | Description | Default | Required |
| - | - | - | - |
| `APP_ENC_KEY` | Master key that encrypts the stored connection credentials. Standard base64 of at least 32 bytes. Outside production, Matcher uses a temporary key when it is unset. Sensitive. | — | Production |
| `FETCHER_DISCOVERY_INTERVAL_SEC` | Seconds between discovery runs against the extraction engine. | `60` | No |
| `FETCHER_SCHEMA_CACHE_TTL_SEC` | Seconds Matcher caches a discovered schema. | `300` | No |
| `FETCHER_EXTRACTION_TIMEOUT_SEC` | Seconds Matcher waits for one extraction. | `600` | No |
| `FETCHER_MAX_EXTRACTION_BYTES` | Maximum size, in bytes, of one extraction result. | `2147483648` | No |

## Connectors

| Variable | Description | Default | Required |
| - | - | - | - |
| `PAGBANK_CONNECTOR_BASE_URL` | PagBank API base URL. | `https://api.pagseguro.com` | No |
| `STRIPE_CONNECTOR_BASE_URL` | Stripe API base URL. | `https://api.stripe.com` | No |
| `STRIPE_CONNECTOR_FILES_BASE_URL` | Stripe files API base URL. | `https://files.stripe.com` | No |
| `PIX_CONNECTOR_BASE_URL` | Pix API base URL. Without it, the Pix connector fails on first use. | — | For the Pix connector |
| `PLUGGY_CONNECTOR_BASE_URL` | Pluggy API base URL. | `https://api.pluggy.ai` | No |
| `PLUGGY_WEBHOOK_HMAC_SECRET` | Secret that verifies Pluggy webhooks. It wins over the IP list. Sensitive. | — | No |
| `PLUGGY_WEBHOOK_ALLOWED_IPS` | Source IPs that Matcher accepts for Pluggy webhooks (CSV). | — | No |
| `BELVO_CONNECTOR_BASE_URL` | Belvo API base URL. | `https://api.belvo.com` | No |
| `BELVO_WEBHOOK_HMAC_SECRET` | Secret that verifies Belvo webhooks. It wins over the IP list. Sensitive. | — | No |
| `BELVO_WEBHOOK_ALLOWED_IPS` | Source IPs that Matcher accepts for Belvo webhooks (CSV). | — | No |

## AI features

Each feature has an on switch, an API key, and a model. Document extraction and rule suggestions also need the consent in the `ai_gates` runtime document. By default, that consent is off.

| Variable | Description | Default | Required |
| - | - | - | - |
| `ADVISOR_ENABLED` | Turns on the mapping advisor. | `false` | No |
| `ADVISOR_ANTHROPIC_API_KEY` | API key for the mapping advisor's language-model provider. Sensitive. | — | When the advisor is on |
| `ADVISOR_MODEL` | Model for the mapping advisor. | `claude-sonnet-4-6` | No |
| `DOC_EXTRACTION_ENABLED` | Turns on document extraction. | `false` | No |
| `DOC_EXTRACTION_ANTHROPIC_API_KEY` | API key for document extraction. Sensitive. | — | When document extraction is on |
| `DOC_EXTRACTION_MODEL` | Model for document extraction. | `claude-sonnet-4-6` | No |
| `RULE_ADVISOR_ENABLED` | Turns on rule suggestions. | `false` | No |
| `RULE_ADVISOR_ANTHROPIC_API_KEY` | API key for rule suggestions. Sensitive. | — | When rule suggestions are on |
| `RULE_ADVISOR_MODEL` | Model for rule suggestions. | `claude-sonnet-4-6` | No |

## Event streaming

| Variable | Description | Default | Required |
| - | - | - | - |
| `STREAMING_ENABLED` | Publishes Matcher events to Kafka. | `false` | No |
| `STREAMING_BROKERS` | Kafka brokers (CSV). | — | When streaming is on |
| `STREAMING_CLIENT_ID` | Kafka client ID. | `primary` | No |
| `STREAMING_CLOUDEVENTS_SOURCE` | Source name on each event. It also names the topic `lerian.streaming.<source>`. One lowercase segment that matches `^[a-z0-9][a-z0-9_-]*$`. Matcher checks the format even when streaming is off. | — | When streaming is on |
| `STREAMING_TLS_ENABLED` | Uses TLS for Kafka. | `false` | Production, when streaming is on |
| `STREAMING_TLS_CA_CERT` | CA certificate for Kafka TLS. | — | No |
| `STREAMING_SASL_MECHANISM` | SASL mechanism: `PLAIN`, `SCRAM-SHA-256`, or `SCRAM-SHA-512`. | — | No |
| `STREAMING_SASL_USERNAME` | SASL user. | — | With a SASL mechanism |
| `STREAMING_SASL_PASSWORD` | SASL password. Sensitive. | — | With a SASL mechanism |
| `STREAMING_SASL_ALLOW_PLAINTEXT` | Allows SASL without TLS. | `false` | No |
| `STREAMING_CB_FAILURE_RATIO` | Failure ratio that opens the publish circuit breaker. | `0.5` | No |
| `STREAMING_CB_MIN_REQUESTS` | Requests the breaker needs before it can open. | `10` | No |
| `STREAMING_CB_TIMEOUT_S` | Seconds the breaker stays open. | `30` | No |
| `STREAMING_CLOSE_TIMEOUT_S` | Seconds Matcher waits to flush events when it stops. | `30` | No |
| `STREAMING_TOPIC_AUTO_PROVISION` | Creates the topic at startup when it does not exist. | `true` | No |
| `STREAMING_TOPIC_PARTITIONS` | Partitions for a created topic. `-1` uses the broker default. | `-1` | No |
| `STREAMING_TOPIC_REPLICATION_FACTOR` | Replication factor for a created topic. `-1` uses the broker default. | `-1` | No |

## Runtime documents

Matcher keeps eleven runtime documents in the Systemplane namespace `matcher`, under `/system`. The variables below set the starting value of each document. After Lerian writes a document through Systemplane, the stored document wins over its variables. The `rate_limit` document cannot turn the limits on while `RATE_LIMIT_ENABLED` is unset or `false`.

| Document | Variables |
| - | - |
| `http` | `HTTP_BODY_LIMIT_BYTES`, `CORS_ALLOWED_ORIGINS`, `CORS_ALLOWED_METHODS`, `CORS_ALLOWED_HEADERS`, `POSTGRES_QUERY_TIMEOUT_SEC`, `HEALTH_CHECK_TIMEOUT_SEC`, `HEALTH_CHECK_TIMEOUT_MS` |
| `rate_limit` | `RATE_LIMIT_ENABLED`, `RATE_LIMIT_MAX`, `RATE_LIMIT_EXPIRY_SEC`, `EXPORT_RATE_LIMIT_MAX`, `EXPORT_RATE_LIMIT_EXPIRY_SEC`, `DISPATCH_RATE_LIMIT_MAX`, `DISPATCH_RATE_LIMIT_EXPIRY_SEC`, `ADMIN_RATE_LIMIT_MAX`, `ADMIN_RATE_LIMIT_EXPIRY_SEC` |
| `ingestion` | `IDEMPOTENCY_RETRY_WINDOW_SEC`, `IDEMPOTENCY_SUCCESS_TTL_HOURS`, `INGESTION_MAX_UPLOAD_BYTES`, `DEDUPE_TTL_SEC` |
| `fetcher` | `FETCHER_DISCOVERY_INTERVAL_SEC`, `FETCHER_SCHEMA_CACHE_TTL_SEC`, `FETCHER_EXTRACTION_TIMEOUT_SEC`, `FETCHER_MAX_EXTRACTION_BYTES` |
| `exception` | `EXCEPTION_DISPUTE_LOCK_TIMEOUT_MS`, `WEBHOOK_TIMEOUT_SEC`, `CALLBACK_RATE_LIMIT_PER_MIN` |
| `matching` | `MATCH_RUN_WORKER_ENABLED`, `MATCH_RUN_WORKER_POLL_INTERVAL_SEC`, `SCHEDULER_INTERVAL_SEC` |
| `reporting` | `EXPORT_WORKER_ENABLED`, `EXPORT_WORKER_POLL_INTERVAL_SEC`, `EXPORT_WORKER_PAGE_SIZE`, `EXPORT_PRESIGN_EXPIRY_SEC`, `CLEANUP_WORKER_ENABLED`, `CLEANUP_WORKER_INTERVAL_SEC`, `CLEANUP_WORKER_BATCH_SIZE`, `CLEANUP_WORKER_GRACE_PERIOD_SEC` |
| `archival` | `ARCHIVAL_WORKER_ENABLED`, `ARCHIVAL_WORKER_INTERVAL_HOURS`, `ARCHIVAL_HOT_RETENTION_DAYS`, `ARCHIVAL_WARM_RETENTION_MONTHS`, `ARCHIVAL_COLD_RETENTION_MONTHS`, `ARCHIVAL_BATCH_SIZE`, `ARCHIVAL_STORAGE_BUCKET`, `ARCHIVAL_STORAGE_CLASS`, `ARCHIVAL_PARTITION_LOOKAHEAD`, `ARCHIVAL_PRESIGN_EXPIRY_SEC` |
| `object_storage` | `OBJECT_STORAGE_ENDPOINT`, `OBJECT_STORAGE_REGION`, `OBJECT_STORAGE_BUCKET`, `OBJECT_STORAGE_USE_PATH_STYLE`, `OBJECT_STORAGE_ALLOW_INSECURE_ENDPOINT` |
| `tenancy` | `MULTI_TENANT_URL`, `MULTI_TENANT_MAX_TENANT_POOLS`, `MULTI_TENANT_IDLE_TIMEOUT_SEC`, `MULTI_TENANT_TIMEOUT`, `MULTI_TENANT_CIRCUIT_BREAKER_THRESHOLD`, `MULTI_TENANT_CIRCUIT_BREAKER_TIMEOUT_SEC`, `MULTI_TENANT_CACHE_TTL_SEC`, `MULTI_TENANT_CONNECTIONS_CHECK_INTERVAL_SEC` |
| `ai_gates` | No variable. The document holds the AI consents, denied by default. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.