Settings are Kubernetes custom resources that configure how the Formance Operator runs your stack. Each setting controls a specific behavior — from database connections to deployment replicas to gateway routing.
Settings are encoded as strings, but under the hood, each setting can be unmarshalled to a specific type. The basic types are string, number, and bool. There are also two complex structures:
- Maps: one-level dictionaries with string values. Repeat the
<key>=<value> pattern for each entry, separated by commas.
- URIs: used to address external resources (Postgres, Kafka, etc.). See URI format reference for details.
How to apply settings
Create a Settings resource and apply it to your cluster. The Operator picks it up automatically.
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: <setting-name>
spec:
stacks:
- '<stack-name>'
key: <setting-key>
value: <setting-value>
The spec fields are:
- stacks: which stacks use this setting. Use
* to apply to all stacks.
- key: the setting key from the tables below. Use
* as a wildcard to match all modules or services (e.g., postgres.*.uri).
- value: the setting value.
Available settings
Infrastructure
| Key | Type | Example | Description |
|---|
| aws.service-account | string | formance-role | AWS IAM role name for service account authentication |
postgres.<module-name>.uri | URI | postgresql://user:pass@host:5432 | Postgres database configuration. See URI format |
| temporal.dsn | URI | temporal://temporal:7233/default | Temporal server URI. See URI format |
| temporal.tls.crt | string | | Temporal TLS certificate (PEM-encoded or Kubernetes secret reference) |
| temporal.tls.key | string | | Temporal TLS certificate key (PEM-encoded or Kubernetes secret reference) |
| broker.dsn | URI | nats://nats:4222 | Message broker URI. See URI format |
| opentelemetry.traces.dsn | URI | grpc://otel-collector:4317 | OpenTelemetry collector URI |
| opentelemetry.traces.resource-attributes | Map | key1=value1,key2=value2 | OpenTelemetry additional resource attributes |
| clear-database | bool | true | Destructive. Remove databases when a stack is deleted |
| logging.json | bool | true | Configure services to output structured JSON logs |
modules.<module-name>.database.connection-pool | Map | max-idle=10, max-idle-time=10s, max-open=10, max-lifetime=5m | Configure database connection pool for each module. See Golang documentation |
modules.<module-name>.grace-period | string | 5s | Set the grace period before application shutdown |
Ledger
| Key | Type | Example | Description |
|---|
| ledger.deployment-strategy | string | single | Set the Ledger deployment type |
| ledger.logs.max-batch-size | Int | 1024 | Set the max batch size for Ledger log writes |
| ledger.api.bulk-max-size | Int | 100 | Set the max number of operations per bulk request |
| ledger.api.default-page-size | Int | 15 | Set the default page size for Ledger list endpoints |
| ledger.api.max-page-size | Int | 100 | Set the maximum allowed page size for Ledger list endpoints |
| ledger.experimental-features | Bool | true | Enable experimental features |
| ledger.experimental-numscript | Bool | true | Enable new numscript interpreter |
| ledger.experimental-numscript-flags | Array | experimental-overdraft-function experimental-get-asset-function | Enable numscript interpreter flags |
| ledger.experimental-exporters | Bool | true | Enable new exporters feature |
| ledger.worker.async-block-hasher | Map | max-block-size=1000, schedule=“0 * * * * *“ | Configure async block hasher for the Ledger worker (v2.3+). Fields: max-block-size, schedule |
| ledger.worker.pipelines | Map | pull-interval=5s, push-retry-period=10s, sync-period=1m, logs-page-size=100 | Configure pipelines for the Ledger worker (v2.3+). Fields: pull-interval, push-retry-period, sync-period, logs-page-size |
| transactionplane.worker-enabled | bool | false | Enable the embedded worker inside the transactionplane server to run a single service |
Payments
| Key | Type | Example | Description |
|---|
| payments.encryption-key | string | | Set the encryption key for Payments data |
| payments.worker.temporal-max-concurrent-workflow-task-pollers | Int | | Set max concurrent workflow task pollers |
| payments.worker.temporal-max-concurrent-activity-task-pollers | Int | | Set max concurrent activity task pollers |
| payments.worker.temporal-max-slots-per-poller | Int | | Set max slots per poller |
| payments.worker.temporal-max-local-activity-slots | Int | | Set max local activity slots |
Orchestration
| Key | Type | Example | Description |
|---|
| orchestration.max-parallel-activities | Int | 10 | Set max parallel Temporal activities on orchestration workers |
Deployments and jobs
| Key | Type | Example | Description |
|---|
deployments.<deployment-name>.replicas | string | 2 | Set the number of pod replicas for the deployment |
deployments.<deployment-name>.semconv-metrics-names | Bool | true | Enable semantic convention metrics names by setting SEMCONV_METRICS_NAME env var to true in all containers |
deployments.<deployment-name>.spec.template.annotations | Map | firstannotation=X, anotherannotation=X | Custom annotations for deployment pod templates |
deployments.<deployment-name>.spec.template.spec.termination-grace-period-seconds | Int | 30 | Set the termination grace period for the deployment |
deployments.<deployment-name>.init-containers.<container-name>.resource-requirements | Map | cpu=X, mem=X | Resource requirements (CPU and memory) for init containers |
deployments.<deployment-name>.containers.<container-name>.resource-requirements | Map | cpu=X, mem=X | Resource requirements (CPU and memory) for containers |
deployments.<deployment-name>.init-containers.<container-name>.run-as | Map | user=X, group=X | Security context (user and group IDs) for init containers |
deployments.<deployment-name>.containers.<container-name>.run-as | Map | user=X, group=X | Security context (user and group IDs) for containers |
deployments.<deployment-name>.topology-spread-constraints | Bool | true | Enable topology spread constraints to maximize high availability |
| caddy.image | string | | Set the Caddy reverse proxy image |
jobs.<owner-kind>.spec.template.annotations | Map | firstannotation=X, anotherannotation=Y | Custom annotations for job pod templates |
jobs.<owner-kind>.init-containers.<container-name>.run-as | Map | user=X, group=X | Security context (user and group IDs) for job init containers |
jobs.<owner-kind>.containers.<container-name>.run-as | Map | user=X, group=X | Security context (user and group IDs) for job containers |
Registries and services
| Key | Type | Example | Description |
|---|
registries.<name>.endpoint | string | example.com?pullSecret=foo | Custom endpoint for a specific docker repository |
registries.<name>.images.<path>.rewrite | string | formancehq/example | Override the image path for a specific registry |
services.<service-name>.annotations | Map | key1=value1,key2=value2 | Custom annotations for Kubernetes services |
services.<service-name>.traffic-distribution | string | PreferSameZone | Configure traffic distribution for Kubernetes services (requires Kubernetes 1.34+) |
Gateway
| Key | Type | Example | Description |
|---|
| gateway.ingress.annotations | Map | cert-manager.io/cluster-issuer=letsencrypt | Custom annotations for the gateway ingress |
| gateway.ingress.hosts | string | .example.com,.example.org | Comma-separated list of additional hosts for the gateway ingress. Supports {stack} placeholder |
| gateway.ingress.labels | Map | env=production,team=platform | Custom labels for the gateway ingress |
| gateway.ingress.tls.enabled | bool | true | Enable TLS if not enabled at Gateway CRD level |
| gateway.caddyfile.trusted-proxies | string | 10.0.0.0/8,192.168.0.0/16 | Comma-separated list of trusted proxy CIDRs. Use private_ranges for all private IPv4/IPv6 ranges |
| gateway.caddyfile.trusted-proxies-strict | bool | false | Enable strict (right-to-left) parsing of X-Forwarded-For header. Recommended with upstream proxies (HAProxy, Cloudflare, ALB) |
| gateway.config.idle-timeout | string | 10m | Idle timeout for client connections (default: 5m). Use Go duration format (e.g., 30s, 5m, 1h) |
| gateway.dns.private.enabled | bool | false | Enable generation of private DNS endpoints for the gateway |
| gateway.dns.private.dns-names | string | .internal.example.com | DNS name pattern(s) for private DNS endpoints. Comma-separated. Supports {stack} placeholder |
| gateway.dns.private.targets | string | internal-lb.example.com | Target(s) for private DNS records. Comma-separated |
| gateway.dns.private.record-type | string | CNAME | DNS record type (e.g., CNAME, A, AAAA) |
| gateway.dns.private.provider-specific | Map | alias=true,aws/target-hosted-zone=same-zone | Provider-specific DNS settings for private endpoints |
| gateway.dns.private.annotations | Map | external-dns.alpha.kubernetes.io/ttl=300 | Annotations for the private DNSEndpoint resource |
| gateway.dns.public.enabled | bool | false | Enable generation of public DNS endpoints for the gateway |
| gateway.dns.public.dns-names | string | .example.com | DNS name pattern(s) for public DNS endpoints. Comma-separated. Supports {stack} placeholder |
| gateway.dns.public.targets | string | public-lb.example.com | Target(s) for public DNS records. Comma-separated |
| gateway.dns.public.record-type | string | CNAME | DNS record type (e.g., CNAME, A, AAAA) |
| gateway.dns.public.provider-specific | Map | alias=true,aws/target-hosted-zone=same-zone | Provider-specific DNS settings for public endpoints |
| gateway.dns.public.annotations | Map | external-dns.alpha.kubernetes.io/ttl=300 | Annotations for the public DNSEndpoint resource |
| networkpolicies.enabled | bool | true | Enable network micro-segmentation within a Stack namespace. Only the Gateway can reach other services |
Namespace
| Key | Type | Example | Description |
|---|
| namespace.labels | Map | somelabel=somevalue,anotherlabel=anothervalue | Add static labels to namespace |
| namespace.annotations | Map | someannotation=somevalue,anotherannotation=anothervalue | Add static annotations to namespace |
Postgres URI format
Scheme: postgresql
Query params:
| Name | Type | Default | Description |
|---|
| secret | string | | Specify a secret where credentials are defined |
| disableSSLMode | bool | false | Disable SSL on Postgres connection |
Scheme: temporal
Path: Match the temporal namespace
Query params:
| Name | Type | Default | Description |
|---|
| secret | string | | Specify a secret where temporal certificates are defined |
| encryptionKeySecret | string | | Specify a secret where temporal encryption key is defined |
| initSearchAttributes | string | false | Initialize search attributes on temporal namespace |
Scheme: nats | kafka
Scheme: nats
Query params:
| Name | Type | Default | Description |
|---|
| replicas | number | 1 | Specify the number of replicas to configure on newly created nats streams |
Scheme: kafka
Query params:
| Name | Type | Default | Description |
|---|
| saslEnabled | bool | false | Specify if SASL authentication must be enabled |
| saslUsername | string | | Username for SASL authentication |
| saslPassword | string | | Password for SASL authentication |
| saslMechanism | string | | Mechanism for SASL authentication |
| saslSCRAMSHASize | string | | SCRAM SHA size for SASL authentication |
| tls | bool | false | Whether to enable SSL |
Examples
Define PostgreSQL clusters
Configure a PostgreSQL cluster for the formance-dev stack, applying to all modules. Each module is isolated in its own database.
Databases are created following the format: {stackName}-{module}
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: formance-dev-postgres-uri
spec:
key: postgres.*.uri
stacks:
- 'formance-dev'
value: postgresql://formance:formance@postgresql.formance-system.svc:5432?disableSSLMode=true
Use AWS IAM Role
Use an AWS IAM role to connect to the database instead of static credentials.
apiVersion: v1
kind: ServiceAccount
metadata:
name: aws-rds-access-role
namespace: formance-system
labels:
formance.com/stack: any
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::AWS_ACCOUNT_ID:role/AWS_ROLE_NAME
---
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: formance-dev-postgres-uri
spec:
key: postgres.*.uri
stacks:
- 'formance-dev'
value: postgresql://formance@postgresql.formance-system.svc:5432
Define module resource requests
Set resource requests for all containers across all modules in the stack.
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: formance-dev-resource-requests
spec:
key: deployments.*.containers.*.resource-requirements.requests
stacks:
- 'formance-dev'
value: cpu=10m,memory=100Mi
Configure database job security context
Set the user and group IDs for database create and drop job containers.
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: formance-dev-database-create-run-as
spec:
key: jobs.database.containers.create-database.run-as
stacks:
- 'formance-dev'
value: user=1234,group=1234
---
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: formance-dev-database-drop-run-as
spec:
key: jobs.database.containers.drop-database.run-as
stacks:
- 'formance-dev'
value: user=1234,group=1234
The operator can generate externaldns.k8s.io/v1alpha1 DNSEndpoint resources for your Gateway components, managed by the external-dns operator. You can configure private and public DNS endpoints independently.
The external-dns operator must be installed in your cluster. The Operator creates DNSEndpoint resources, but external-dns is responsible for creating the actual DNS records.
Private DNS Endpoint
Configure a private DNS endpoint for the formance-dev stack.
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: formance-dev-dns-private-enabled
spec:
key: gateway.dns.private.enabled
stacks:
- 'formance-dev'
value: "true"
---
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: formance-dev-dns-private-dns-names
spec:
key: gateway.dns.private.dns-names
stacks:
- 'formance-dev'
value: "{stack}-eks-euw1-01.dev.acme.frmnc.net,{stack}.dev.acme.frmnc.net"
---
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: formance-dev-dns-private-targets
spec:
key: gateway.dns.private.targets
stacks:
- 'formance-dev'
value: "rp-01-eks-euw1-01.dev.acme.frmnc.net"
---
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: formance-dev-dns-private-provider-specific
spec:
key: gateway.dns.private.provider-specific
stacks:
- 'formance-dev'
value: "alias=true,aws/target-hosted-zone=same-zone"
---
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: formance-dev-dns-private-annotations
spec:
key: gateway.dns.private.annotations
stacks:
- 'formance-dev'
value: "service.beta.kubernetes.io/aws-load-balancer-internal=true"
Public DNS Endpoint
Configure a public DNS endpoint for the formance-dev stack.
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: formance-dev-dns-public-enabled
spec:
key: gateway.dns.public.enabled
stacks:
- 'formance-dev'
value: "true"
---
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: formance-dev-dns-public-dns-names
spec:
key: gateway.dns.public.dns-names
stacks:
- 'formance-dev'
value: "{stack}.acme.frmnc.net"
---
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: formance-dev-dns-public-targets
spec:
key: gateway.dns.public.targets
stacks:
- 'formance-dev'
value: "rp-01-eks-euw1-01.dev.acme.frmnc.net"
---
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: formance-dev-dns-public-provider-specific
spec:
key: gateway.dns.public.provider-specific
stacks:
- 'formance-dev'
value: "alias=true,aws/target-hosted-zone=same-zone"
DNS Settings Details
-
DNS Names: The
dns-names setting supports the {stack} placeholder which will be replaced with the actual stack name. You can specify multiple DNS names by separating them with commas. Each DNS name will create a separate endpoint in the DNSEndpoint resource.
-
Targets: Multiple targets can be specified by separating them with commas. All targets will be added to each DNS record endpoint.
-
Record Type: Defaults to
CNAME if not specified. Common values include CNAME, A, AAAA, TXT, etc.
-
Provider-Specific Settings: These are provider-specific DNS configurations. For AWS Route53, common settings include:
alias=true: Enable alias records
aws/target-hosted-zone=same-zone: Use the same hosted zone for the target
-
Annotations: Annotations added to the DNSEndpoint resource. Useful for provider-specific configurations or metadata.
The operator can create Kubernetes NetworkPolicies to enforce network micro-segmentation within a Stack namespace. When enabled:
- All ingress traffic is denied by default
- The Gateway is accessible by everyone (entry point)
- All other services are only accessible from the Gateway
Egress traffic is not restricted.
A CNI plugin that supports NetworkPolicies (Calico, Cilium, etc.) must be installed in your cluster. The default CNI in some environments (e.g., Flannel) does not enforce NetworkPolicies.
apiVersion: formance.com/v1beta1
kind: Settings
metadata:
name: enable-networkpolicies
spec:
key: networkpolicies.enabled
stacks:
- '*'
value: "true"
When enabled, 3 NetworkPolicies are created in the Stack namespace:
| Name | Effect |
|---|
default-deny-ingress | Denies all ingress traffic to all pods |
allow-gateway-ingress | Allows all ingress traffic to pods labeled app.kubernetes.io/name: gateway |
allow-from-gateway | Allows ingress traffic from gateway pods to all other pods |
Since Kubernetes NetworkPolicies are additive, the Gateway receives both deny-all and allow-all, making it fully accessible. Other services receive deny-all and allow-from-gateway, restricting access to Gateway only.
If no Gateway module is deployed, the policies are still created. The deny-all policy protects all services, and the allow-from-gateway rule has no matching source — resulting in all ingress being blocked, which is the safest default.