# UDB (Universal Data Broker) environment template.
#
# Copy this file to `.env.local` for development or `.env.prod` for production.
# Keep real secrets out of git.
#
# Dotenv load order, first value wins:
# 1. OS environment
# 2. .env.<APP_ENV>
# 3. .env.local
# 4. .env.prod
# 5. .env
#
# build.rs and the CLI probe this repo and its parent directory, so the same
# env files work when UDB is used standalone or embedded in a larger workspace.
# ---------------------------------------------------------------------------
# Required for a normal broker
# ---------------------------------------------------------------------------
APP_ENV=local
UDB_ENV=development
UDB_APP_NAME=udb-broker
# PostgreSQL is the canonical store. `UDB_PG_DSN` may also be supplied as
# `DATABASE_URL`; the explicit UDB_* name is preferred in UDB deployments.
UDB_PG_INSTANCES=primary
UDB_PG_DSN_PRIMARY=postgresql://user:pass@host:5432/dbname?sslmode=require
UDB_PG_DSN=postgresql://user:pass@host:5432/dbname?sslmode=require
# DATABASE_URL=postgresql://user:pass@host:5432/dbname?sslmode=require
# Pool defaults used by the Postgres runtime.
UDB_PG_MIN_CONNECTIONS=0
UDB_PG_MAX_CONNECTIONS=10
UDB_PG_IDLE_TIMEOUT=240
UDB_PG_MAX_LIFETIME=900
UDB_PG_ACQUIRE_TIMEOUT=30
# Two-phase commit is intentionally opt-in.
UDB_2PC_ENABLED=false
# ---------------------------------------------------------------------------
# Build and CLI discovery
# ---------------------------------------------------------------------------
# Proto defaults are auto-detected from ./proto. Set only for non-standard
# layouts or when embedding UDB under another workspace.
# UDB_PROTO_ROOT=proto
# UDB_PROTO_DIR=proto
# UDB_PROTO_PREFIX=udb
# UDB_PROTO_NAMESPACE=udb
# UDB_PROTO_PREFIX_FORCE=1
# Optional YAML config path. The CLI maps common YAML fields into env vars.
# UDB_CONFIG_PATH=configs/database.yaml
# Scaffold/init output directory.
# UDB_INIT_DIR=.
# ---------------------------------------------------------------------------
# Core runtime limits
# ---------------------------------------------------------------------------
# UDB_DEFAULT_LIMIT=100
# UDB_MAX_LIMIT=10000
# UDB_DDL_CONCURRENCY=4
# UDB_MATERIALIZED_VIEW_TTL_DAYS=30
# UDB_ALLOW_DEGRADED_BACKENDS=false
# UDB_CATALOG_COMPATIBILITY_WARN_ONLY=false
# UDB_CATALOG_COMPAT_WARN_ONLY=false
# UDB_CATALOG_COMPATIBILITY_LEVEL=backward
# UDB_PROJECT_ROUTING_MODE=default
# UDB_RAW_DISPATCH_POLICY=deny
# UDB_CONSISTENCY_FENCE_POLL_MS=50
# ---------------------------------------------------------------------------
# Observability
# ---------------------------------------------------------------------------
RUST_LOG=info
# UDB_LOG_JSON=false
# UDB_NO_COLOR=false
# NO_COLOR=1
# UDB_REPORT_JSON=false
# UDB_LINT_HUMAN=true
# Metrics / service endpoints.
# UDB_GRPC_ADDR=127.0.0.1:50051
# UDB_GRPC_TIMEOUT_SECS=30
# UDB_GRPC_MAX_CONCURRENT=1024
# UDB_METRICS_ADDR=127.0.0.1:50052
# UDB_METRICS_ALLOWED_CIDR=127.0.0.1/32
# UDB_METRIC_ENDPOINT_ALLOWLIST=127.0.0.1/32
# UDB_RATE_LIMIT_WINDOW_SECS=60
# UDB_RATE_LIMIT_MAX_PER_WINDOW=1000
# ---------------------------------------------------------------------------
# PostgreSQL routing and replicas
# ---------------------------------------------------------------------------
# Multi-instance routing. For each name in UDB_PG_INSTANCES, define
# UDB_PG_DSN_<UPPERCASE_NAME>.
# UDB_PG_INSTANCES=primary,analytics
# UDB_PG_DSN_ANALYTICS=postgresql://user:pass@host:5432/analytics?sslmode=require
# UDB_PG_PRIMARY_ENABLED=true
# UDB_PG_DEPLOY_MODE=self_hosted
# Read replicas.
# UDB_PG_REPLICA_DSN=postgresql://user:pass@replica:5432/dbname?sslmode=require
# UDB_PG_REPLICA_DSNS=postgresql://user:pass@replica1:5432/dbname,postgresql://user:pass@replica2:5432/dbname
# UDB_PG_REPLICA_STRATEGY=round_robin
# UDB_PG_REPLICA_MAX_LAG_SECS=5
# UDB_PG_REPLICA_FAIL_OPEN=false
# UDB_PG_REPLICA_MIN_CONNECTIONS=0
# UDB_PG_REPLICA_MAX_CONNECTIONS=10
# UDB_PG_REPLICA_HEALTH_INTERVAL_SECS=15
# ---------------------------------------------------------------------------
# Optional backend connections
# ---------------------------------------------------------------------------
# Redis cache. REDIS_URL is accepted as an alias.
# UDB_REDIS_DSN=redis://127.0.0.1:6379/0
# REDIS_URL=redis://127.0.0.1:6379/0
# UDB_REDIS_DEPLOY_MODE=self_hosted
# Qdrant vector store. QDRANT_URL is accepted as an alias.
# UDB_QDRANT_URL=http://127.0.0.1:6333
# QDRANT_URL=http://127.0.0.1:6333
# UDB_QDRANT_API_KEY=
# UDB_QDRANT_DSN=http://127.0.0.1:6333
# UDB_QDRANT_DEPLOY_MODE=self_hosted
# UDB_QDRANT_TIMEOUT_SECS=30
# S3-compatible object storage / MinIO. The runtime reads UDB_MINIO_*.
# AWS_* and AWS_ENDPOINT_URL are accepted by the YAML/env projection path.
# UDB_MINIO_ENDPOINT=http://127.0.0.1:9000
# UDB_MINIO_ACCESS_KEY=minioadmin
# UDB_MINIO_SECRET_KEY=minioadmin
# UDB_MINIO_REGION=us-east-1
# UDB_MINIO_DSN=http://127.0.0.1:9000
# UDB_MINIO_DEPLOY_MODE=self_hosted
# AWS_ENDPOINT_URL=http://127.0.0.1:9000
# AWS_ACCESS_KEY_ID=minioadmin
# AWS_SECRET_ACCESS_KEY=minioadmin
# AWS_REGION=us-east-1
# UDB_S3_BUCKET=udb-objects
# UDB_S3_DSN=http://127.0.0.1:9000
# MongoDB / Atlas Data API. The broker uses UDB_NOSQL_*; UDB_MONGO_URI is
# retained only as a legacy/operator note and is not the primary runtime name.
# UDB_NOSQL_DSN=mongodb://127.0.0.1:27017/udb
# UDB_NOSQL_API_URL=http://127.0.0.1:27017
# UDB_NOSQL_API_KEY=
# UDB_NOSQL_DATABASE=udb
# UDB_NOSQL_TIMEOUT_SECS=30
# UDB_MONGO_DEPLOY_MODE=self_hosted
# UDB_MONGO_URI=mongodb://127.0.0.1:27017/udb
# Neo4j graph.
# UDB_GRAPH_DSN=bolt://neo4j:password@127.0.0.1:7687
# UDB_GRAPH_HTTP_URL=http://127.0.0.1:7474
# UDB_GRAPH_USER=neo4j
# UDB_GRAPH_PASSWORD=password
# UDB_GRAPH_DATABASE=neo4j
# UDB_GRAPH_TIMEOUT_SECS=30
# UDB_NEO4J_DEPLOY_MODE=self_hosted
# ClickHouse column store.
# UDB_COLUMN_DSN=clickhouse://default:password@127.0.0.1:8123/udb
# UDB_COLUMN_HTTP_URL=http://127.0.0.1:8123
# UDB_COLUMN_USER=default
# UDB_COLUMN_PASSWORD=password
# UDB_COLUMN_DATABASE=udb
# UDB_CH_DEPLOY_MODE=self_hosted
# UDB_CH_CONNECT_TIMEOUT_SECS=10
# UDB_CH_QUERY_TIMEOUT_SECS=30
# Other backend plugins.
# UDB_MYSQL_DSN=mysql://user:pass@127.0.0.1:3306/udb
# UDB_SQLITE_DSN=sqlite://udb.sqlite
# UDB_MSSQL_DSN=Server=127.0.0.1,1433;User=sa;Password=yourStrong(!)Password;Database=udb;TrustServerCertificate=true
# UDB_ELASTIC_DSN=http://elastic:password@127.0.0.1:9200
# UDB_MEMCACHED_DSN=memcached://127.0.0.1:11211
# UDB_WEAVIATE_DSN=http://127.0.0.1:8080
# UDB_PINECONE_DSN=apikey://<api-key>@<host>
# UDB_CASSANDRA_DSN=127.0.0.1:9042
# UDB_AZUREBLOB_DSN=DefaultEndpointsProtocol=https;AccountName=<name>;AccountKey=<key>;EndpointSuffix=core.windows.net
# UDB_GCS_DSN=<gcp-project-id>
# GOOGLE_APPLICATION_CREDENTIALS=/absolute/path/to/service-account.json
# Generated DSN aliases used by provisioning/catalog code and playgrounds.
# UDB_SQL_DSN=postgresql://user:pass@host:5432/dbname?sslmode=require
# UDB_CACHE_DSN=redis://127.0.0.1:6379/0
# UDB_VECTOR_DSN=http://127.0.0.1:6333
# UDB_OBJECT_DSN=http://127.0.0.1:9000
# UDB_TIMESERIES_DSN=postgresql://user:pass@host:5432/timeseries?sslmode=require
# UDB_GENERIC_DSN=
# UDB_NOTADB_DSN=
# Named backend inventory. The runtime also supports per-instance env vars.
# Keep this empty unless you are explicitly using multi-backend routing.
# UDB_BACKEND_INSTANCES=
# UDB_BACKEND_INSTANCE_<NAME>_KIND=postgres
# UDB_BACKEND_INSTANCE_<NAME>_DSN_ENV=UDB_PG_DSN_PRIMARY
# ---------------------------------------------------------------------------
# Kafka and CDC
# ---------------------------------------------------------------------------
# UDB_KAFKA_BROKERS=127.0.0.1:9092
# KAFKA_BROKERS=127.0.0.1:9092
# UDB_KAFKA_TLS_REQUIRED=false
# UDB_KAFKA_TX_TIMEOUT_SECS=30
# CDC storage objects and replication settings.
# UDB_CDC_SYSTEM_SCHEMA=udb_system
# UDB_CDC_OUTBOX_TABLE=udb_cdc_outbox
# UDB_CDC_OFFSETS_TABLE=udb_cdc_offsets
# UDB_CDC_LOCK_LOG_TABLE=udb_cdc_lock_log
# UDB_CDC_PUBLICATION=udb_publication
# UDB_CDC_SLOT=udb_slot
# UDB_CDC_ADVISORY_LOCK_KEY=42000
# UDB_CDC_VALID_TOPICS=udb.events,udb.dlq
# UDB_CDC_DLQ_TOPIC=udb.dlq
# UDB_CDC_SCHEMA_URI_TEMPLATE=
# UDB_SCHEMA_REGISTRY_URL=
# UDB_SCHEMA_REGISTRY_AUTH=
# UDB_SCHEMA_REGISTRY_MODE=disabled
# UDB_CDC_SCHEMA_REGISTRY_MODE=disabled
# UDB_CDC_RETRY_TOPIC_PREFIX=udb.retry
# UDB_CDC_MAX_RETRY_ATTEMPTS=3
# UDB_CDC_RETRY_DELAY_SECS=5
# UDB_CDC_TLS=false
# UDB_CDC_MAX_WAL_LAG_BYTES=67108864
# UDB_CDC_EXACTLY_ONCE_MODE=false
# UDB_CDC_TRANSACTIONAL_ID_PREFIX=udb-cdc
# UDB_CDC_PRODUCER_EPOCH=0
# UDB_CDC_KAFKA_TX_TIMEOUT_SECS=30
# UDB_CDC_REDACTION_MODE=metadata
# UDB_CDC_REDACTION_VERSION=1
# UDB_CDC_INDOUBT_GRACE_SECS=60
# ---------------------------------------------------------------------------
# Authorization, identity, and security
# ---------------------------------------------------------------------------
# ABAC policy source.
# UDB_ABAC_POLICIES_JSON=[]
# UDB_ABAC_POLICY_FILE=policies/abac.json
# UDB_ABAC_SCHEMA=udb_system
# UDB_ABAC_TABLE=udb_abac_policies
# UDB_ABAC_REFRESH_SECS=60
# UDB_ABAC_DEFAULT_ALLOW=false
# Request identity and client/project defaults.
# UDB_SERVICE_IDENTITY_REQUIRED=true
# UDB_SERVICE_IDENTITY=udb-broker
# UDB_PROJECT_ID=default
# UDB_DEFAULT_PURPOSE=service.request
# UDB_DEFAULT_SCOPES=udb:read,udb:write
# UDB_CLIENT_CATALOG_VERSION=1.0.0
# UDB_ALLOW_HEADER_SCOPES=false
# UDB_JWT_PUBLIC_KEY=/absolute/path/to/jwt-public-key.pem
# TLS/mTLS for the broker.
# UDB_TLS_REQUIRED=false
# UDB_TLS_CERT_PATH=/absolute/path/to/server.crt
# UDB_TLS_KEY_PATH=/absolute/path/to/server.key
# UDB_TLS_CERT_PEM=
# UDB_TLS_KEY_PEM=
# UDB_MTLS_REQUIRED=false
# UDB_MTLS_CLIENT_CA_PATH=/absolute/path/to/ca.crt
# UDB_MTLS_CLIENT_CA_PEM=
# UDB_TLS_CA_CERT_PATH=/absolute/path/to/ca.crt
# Backend TLS expectations.
# UDB_PG_TLS_REQUIRED=true
# UDB_REDIS_TLS_REQUIRED=true
# Security/audit controls.
# UDB_PII_SAFE_LOGGING=true
# UDB_AUDIT_SINK=none
# UDB_AUDIT_SINK_URL=
# UDB_AUDIT_FILE_PATH=logs/audit.log
# UDB_AUDIT_KAFKA_TOPIC=udb.audit
# UDB_AUDIT_KAFKA_BROKERS=127.0.0.1:9092
# UDB_AUDIT_PG_TABLE=udb_system.udb_admin_audit_log
# UDB_AUDIT_MIN_SEVERITY=info
# ---------------------------------------------------------------------------
# Encryption and Vault
# ---------------------------------------------------------------------------
# UDB_ENCRYPTION_KEY=
# UDB_ENCRYPTION_KEYS=
# UDB_ENCRYPTION_KEY_V1=
# UDB_ENCRYPTION_KEY_V2=
# UDB_ENCRYPTION_ACTIVE_VERSION=1
# UDB_ENCRYPTION_KEY_ID=
# UDB_ENCRYPTION_KEY_ROTATION=false
# UDB_VAULT_ADDR=https://vault.example.com
# VAULT_ADDR=https://vault.example.com
# UDB_VAULT_TOKEN=
# VAULT_TOKEN=
# UDB_VAULT_TRANSIT_KEY_NAME=udb
# UDB_VAULT_TRANSIT_MOUNT=transit
# UDB_VAULT_TIMEOUT_SECS=5
# UDB_DEV_MODE=false
# ---------------------------------------------------------------------------
# Saga, XA, migrations, and approvals
# ---------------------------------------------------------------------------
# UDB_SAGA_RECOVERY_ENABLED=true
# UDB_SAGA_RECOVERY_INTERVAL_SECONDS=30
# UDB_SAGA_STALE_THRESHOLD_SECONDS=300
# UDB_CIRCUIT_FAILURE_THRESHOLD=5
# UDB_CIRCUIT_COOLDOWN_SECS=30
# UDB_XA_RECOVERY_INTERVAL_SECS=60
# UDB_XA_RECOVERY_MAX_ATTEMPTS=3
# UDB_DB_OPS_ROOT=db_ops
# UDB_DB_OPS_BACKEND=postgres
# UDB_DB_OPS_FORCE_BOOTSTRAP=false
# UDB_SEEDERS_PATH=db_ops/seeds
# UDB_SEEDER_PATH=db_ops/seeds
# UDB_FORCE_SYNC_LOCK_TIMEOUT_SECS=10
# UDB_FORCE_SYNC_LOCK_POLL_MS=500
# UDB_DRY_RUN_MANIFEST_FETCH_TIMEOUT_SECS=5
# UDB_PRIOR_MANIFEST_PATH=
# UDB_MANIFEST_EXPORT_PATH=
# UDB_FIELD_MASK_SCOPE=
# UDB_APPROVAL_QUORUM_SIZE=1
# UDB_APPROVAL_EXPIRY_SECS=86400
# UDB_APPROVAL_ALLOWED_ROLES=
# UDB_APPROVAL_SIGNING_KEY=
# ---------------------------------------------------------------------------
# Projections
# ---------------------------------------------------------------------------
# UDB_PROJECTION_ENABLED=false
# UDB_PROJECTION_POLL_INTERVAL_SECS=5
# UDB_PROJECTION_BATCH_SIZE=100
# UDB_PROJECTION_MAX_RETRIES=3
# UDB_PROJECTION_RECONCILE_ENABLED=false
# UDB_PROJECTION_RECONCILE_INTERVAL_SECS=60
# UDB_PROJECTION_STALE_IN_PROGRESS_SECS=300
# UDB_PROJECTION_RECONCILE_MAX_SOURCE_ROWS=10000
# ---------------------------------------------------------------------------
# System catalog table overrides
# ---------------------------------------------------------------------------
# UDB_SAGA_TABLE=udb_saga_coordinator
# UDB_CATALOG_VERSIONS_TABLE=udb_catalog_versions
# UDB_CATALOG_ACTIVATION_LOG_TABLE=udb_catalog_activation_log
# UDB_PROJECT_CATALOG_BINDINGS_TABLE=udb_project_catalog_bindings
# UDB_CATALOG_RELOAD_LOG_TABLE=udb_catalog_reload_log
# UDB_MIGRATION_RUNS_TABLE=udb_migration_runs
# UDB_MIGRATION_OP_LEDGER_TABLE=udb_migration_op_ledger
# UDB_CDC_JOURNAL_TABLE=udb_cdc_event_journal
# UDB_DLQ_TABLE=udb_cdc_dlq_events
# UDB_CDC_CONTROL_TABLE=udb_cdc_control
# UDB_TOPIC_POLICY_TABLE=udb_topic_policy
# UDB_ADMIN_AUDIT_LOG_TABLE=udb_admin_audit_log
# UDB_PROJECTS_TABLE=udb_projects
# UDB_PROJECTION_TASKS_TABLE=udb_projection_tasks
# ---------------------------------------------------------------------------
# Channel limits, queues, deadlines, and fairness
# ---------------------------------------------------------------------------
# Global operation budgets.
# UDB_READ_MAX_CONCURRENT=128
# UDB_WRITE_MAX_CONCURRENT=64
# UDB_TX_MAX_CONCURRENT=32
# UDB_MIGRATION_MAX_CONCURRENT=8
# UDB_CDC_MAX_CONCURRENT=16
# UDB_ADMIN_MAX_CONCURRENT=8
# UDB_VECTOR_MAX_CONCURRENT=32
# UDB_OBJECT_MAX_CONCURRENT=32
# UDB_GENERIC_MAX_CONCURRENT=32
# Per-operation timeouts.
# UDB_READ_TIMEOUT_SECS=30
# UDB_WRITE_TIMEOUT_SECS=30
# UDB_TX_TIMEOUT_SECS=60
# UDB_MIGRATION_TIMEOUT_SECS=300
# UDB_CDC_TIMEOUT_SECS=60
# UDB_ADMIN_TIMEOUT_SECS=60
# UDB_VECTOR_TIMEOUT_SECS=30
# UDB_OBJECT_TIMEOUT_SECS=30
# UDB_GENERIC_TIMEOUT_SECS=30
# Queue wait budgets.
# UDB_READ_QUEUE_TIMEOUT_MS=1000
# UDB_WRITE_QUEUE_TIMEOUT_MS=1000
# UDB_TX_QUEUE_TIMEOUT_MS=1000
# UDB_MIGRATION_QUEUE_TIMEOUT_MS=5000
# UDB_CDC_QUEUE_TIMEOUT_MS=5000
# UDB_ADMIN_QUEUE_TIMEOUT_MS=5000
# UDB_VECTOR_QUEUE_TIMEOUT_MS=1000
# UDB_OBJECT_QUEUE_TIMEOUT_MS=1000
# UDB_GENERIC_QUEUE_TIMEOUT_MS=1000
# Fine-grained limits. Operation suffixes include READ, WRITE, TX,
# MIGRATION, CDC, ADMIN, VECTOR, OBJECT, and GENERIC.
# UDB_CHANNEL_READ_LIMIT=128
# UDB_CHANNEL_TENANT_<TENANT>_<OP>_LIMIT=32
# UDB_CHANNEL_PROJECT_<PROJECT>_<OP>_LIMIT=32
# UDB_CHANNEL_INSTANCE_<INSTANCE>_<OP>_LIMIT=32
# UDB_CHANNEL_BACKEND_INSTANCE_<BACKEND>_<INSTANCE>_<OP>_LIMIT=32
# UDB_DEADLINE_<BACKEND>_<OP>_SECS=30
# UDB_FAIR_TOKENS_PER_SEC=100
# UDB_FAIR_BURST=200
# UDB_FAIR_<OP>_TOKENS_PER_SEC=100
# UDB_FAIR_<OP>_BURST=200
# UDB_FAIR_DEFAULT_WEIGHT=1
# UDB_FAIR_PROJECT_<PROJECT>_<OP>_WEIGHT=1
# UDB_FAIR_TENANT_<TENANT>_<OP>_WEIGHT=1
# UDB_FAIR_PROJECT_<PROJECT>_TENANT_<TENANT>_<OP>_WEIGHT=1
# ---------------------------------------------------------------------------
# SDK/client-side .env keys
# ---------------------------------------------------------------------------
# PHP/Laravel and other external clients read these when connecting to UDB.
# They are not required by the Rust broker itself.
# UDB_ENDPOINT=127.0.0.1:50051
# UDB_DEADLINE_MS=30000
# UDB_TLS_ENABLED=false
# UDB_TLS_ROOT_CERTS=/absolute/path/to/ca.pem
# UDB_TLS_TARGET=udb.prod.svc.cluster.local
# UDB_GRPC_KEEPALIVE_MS=30000
# UDB_GRPC_KEEPALIVE_TIMEOUT_MS=10000
# UDB_GRPC_MAX_RECV_BYTES=16777216
# UDB_MIDDLEWARE_AUTO=true
# ---------------------------------------------------------------------------
# Local playground helpers
# ---------------------------------------------------------------------------
# UDB_DOCKER=false
# UDB_PORT=50051
# UDB_FORCE_RESEED=false