Configuration Reference
Dvara is configured through application.yml with environment variable overrides. All configuration lives under the gateway namespace.
Configuration Hierarchy
Configuration is resolved in this order (later sources override earlier ones):
- Defaults — Hardcoded in
application.yml application.yml— File-based configuration- Environment variables — Override any property (e.g.,
OPENAI_API_KEY) - System properties — JVM
-Dflags
Full Application Configuration
gateway:
# ── Provider Configuration ──
providers:
openai:
api-key: ${OPENAI_API_KEY:} # blank = provider disabled
base-url: https://api.openai.com/v1 # override for Azure/proxy
anthropic:
api-key: ${ANTHROPIC_API_KEY:}
gemini:
api-key: ${GEMINI_API_KEY:}
ollama:
enabled: ${OLLAMA_ENABLED:false}
base-url: ${OLLAMA_BASE_URL:http://localhost:11434}
bedrock:
enabled: ${BEDROCK_ENABLED:false}
access-key: ${AWS_ACCESS_KEY_ID:}
secret-key: ${AWS_SECRET_ACCESS_KEY:}
region: ${AWS_REGION:us-east-1}
mock:
enabled: ${MOCK_PROVIDER_ENABLED:false}
response: "This is a mock response" # static text or script
latency-ms: 100 # simulated delay
stream-token-delay-ms: 20 # inter-token SSE delay
error-rate: 0.0 # 0.0–1.0 failure fraction
# ── Route Configuration ──
routes:
- id: load-balance-gpt
model-pattern: "gpt*"
strategy: round-robin
providers:
- provider: openai
- provider: bedrock
- id: weighted-claude
model-pattern: "claude*"
strategy: weighted
providers:
- provider: anthropic
weight: 70
- provider: bedrock
weight: 30
# ── Resilience ──
resilience:
retry:
max-attempts: 3
wait-duration-ms: 500
circuit-breaker:
failure-rate-threshold: 50
sliding-window-size: 20
wait-duration-in-open-state-ms: 30000
timeout:
chat-timeout-ms: 30000
streaming-timeout-ms: 120000
# ── Rate Limiting ──
rate-limit:
enabled: false
global:
requests-per-second: 100
default-per-key:
requests-per-second: 10
tokens-per-minute: 100000
keys:
sk-premium-key:
requests-per-second: 50
tokens-per-minute: 500000
# ── Region Configuration ──
region:
id: ${GATEWAY_REGION_ID:} # region identity (blank = region-unaware)
name: ${GATEWAY_REGION_NAME:} # human-readable region name
# ── Response Caching ──
cache:
enabled: false
ttl-seconds: 3600
max-size: 10000
redis:
enabled: false
# ── Observability ──
management:
endpoints:
web:
exposure:
include: health,prometheus,gateway-status # exposed actuator endpoints
endpoint:
health:
show-details: when-authorized
prometheus:
metrics:
export:
enabled: true # enable Prometheus scrape endpoint
tracing:
sampling:
probability: ${TRACING_SAMPLING_PROBABILITY:1.0} # 0.0–1.0
otlp:
tracing:
endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT:http://localhost:4318/v1/traces}
# ── Spring Boot settings ──
spring:
threads:
virtual:
enabled: true # Project Loom virtual threads
# profiles:
# active: log-plain # switch from JSON to plain-text logging
server:
port: 8080
Environment Variable Reference
| Environment Variable | Property | Description |
|---|---|---|
OPENAI_API_KEY | gateway.providers.openai.api-key | OpenAI API key |
ANTHROPIC_API_KEY | gateway.providers.anthropic.api-key | Anthropic API key |
GEMINI_API_KEY | gateway.providers.gemini.api-key | Google Gemini API key |
OLLAMA_ENABLED | gateway.providers.ollama.enabled | Enable Ollama provider |
OLLAMA_BASE_URL | gateway.providers.ollama.base-url | Ollama server URL |
BEDROCK_ENABLED | gateway.providers.bedrock.enabled | Enable AWS Bedrock provider |
AWS_ACCESS_KEY_ID | gateway.providers.bedrock.access-key | AWS access key for Bedrock |
AWS_SECRET_ACCESS_KEY | gateway.providers.bedrock.secret-key | AWS secret key for Bedrock |
AWS_REGION | gateway.providers.bedrock.region | AWS region for Bedrock |
MOCK_PROVIDER_ENABLED | gateway.providers.mock.enabled | Enable mock provider for testing |
GATEWAY_REGION_ID | gateway.region.id | Region identity for this gateway instance |
GATEWAY_REGION_NAME | gateway.region.name | Human-readable region name |
TRACING_SAMPLING_PROBABILITY | management.tracing.sampling.probability | Trace sampling rate (0.0–1.0, default: 1.0) |
OTEL_EXPORTER_OTLP_ENDPOINT | management.otlp.tracing.endpoint | OTLP HTTP endpoint for trace export |
GATEWAY_COMPLIANCE_SOC2_SCHEDULE | gateway.compliance.soc2-schedule | Cron expression for scheduled SOC2 reports |
GATEWAY_COMPLIANCE_HIPAA_SCHEDULE | gateway.compliance.hipaa-schedule | Cron expression for scheduled HIPAA reports |
GATEWAY_COMPLIANCE_GDPR_SCHEDULE | gateway.compliance.gdpr-schedule | Cron expression for scheduled GDPR reports |
GATEWAY_COMPLIANCE_DEFAULT_TENANT | gateway.compliance.default-tenant-id | Tenant for scheduled reports (blank = all) |
GATEWAY_COMPLIANCE_RETENTION_DAYS | gateway.compliance.retention-days | Report retention period (default: 365) |
GATEWAY_PII_ENABLED | gateway.pii.enabled | Enable PII detection (default: true) |
GATEWAY_PII_DEFAULT_ACTION | gateway.pii.default-action | Default PII action: LOG, BLOCK, REDACT |
GATEWAY_PII_SCAN_RESPONSES | gateway.pii.scan-responses | Scan LLM responses for PII (default: true) |
GATEWAY_PII_STRIP_BEFORE_CACHE | gateway.pii.strip-before-cache | Redact PII before caching (default: true) |
GATEWAY_PII_TOKEN_ENCRYPTION_PASSWORD | gateway.pii.token-encryption-password | AES-256-GCM key for PII token encryption |
GATEWAY_PII_MAX_TOKENS_PER_TENANT | gateway.pii.max-tokens-per-tenant | Max PII tokens per tenant (default: 50000) |
GATEWAY_PII_TOKEN_RETENTION_DAYS | gateway.pii.token-retention-days | PII token retention period (default: 30) |
GATEWAY_CONFIG_FILE | — | Path to gateway.yaml (default: ./gateway.yaml) |
GATEWAY_API_KEY | — | Static API key for standalone mode |
GATEWAY_BOOTSTRAP_FILE | — | Path to bootstrap.yaml for first-startup seeding |
Bootstrap File Seeding
Set GATEWAY_BOOTSTRAP_FILE to a YAML file path to seed tenants, API keys, and routes on first startup. This is designed for full unlicensed mode where state is persisted in a database.
GATEWAY_BOOTSTRAP_FILE=./bootstrap.yaml ./mvnw -pl gateway-server spring-boot:run
The bootstrap loader is idempotent: it checks the config version and skips seeding if any configuration has already been applied (from a previous startup or from gateway.yaml). See examples/bootstrap/bootstrap.yaml in the repository for a complete example.
tenants:
- id: acme-corp
name: Acme Corp
status: active
api_keys:
- tenant: acme-corp
name: production-key
key: ${ACME_API_KEY} # env var reference
- tenant: acme-corp
name: dev-key
generate: true # auto-generated, printed at startup
routes:
- id: gpt-route
model: "gpt*"
provider: openai
Key differences from gateway.yaml:
gateway.yamlis for standalone mode (in-memory, no database)bootstrap.yamlis for full unlicensed mode (seeds a database on first startup)- Both support
$\{ENV_VAR\}and${ENV_VAR:-default}references
Standalone Configuration (gateway.yaml)
In standalone mode (GATEWAY_MODE=standalone), the gateway reads a gateway.yaml file to configure providers, routes, API keys, and rate limits — all without a database.
File Location
| Method | Example |
|---|---|
| Default | ./gateway.yaml in working directory |
| Environment variable | GATEWAY_CONFIG_FILE=/etc/dvara/gateway.yaml |
Full Schema Reference
# gateway.yaml — standalone mode configuration
providers:
- name: openai # unique provider name
type: openai # provider type (see table below)
api_key: ${OPENAI_API_KEY} # env var reference resolved at startup
base_url: https://api.openai.com/v1 # optional override (Azure, proxy)
- name: anthropic
type: anthropic
api_key: ${ANTHROPIC_API_KEY}
- name: gemini
type: gemini
api_key: ${GEMINI_API_KEY}
- name: ollama
type: ollama
base_url: ${OLLAMA_BASE_URL:-http://localhost:11434}
- name: bedrock
type: bedrock
access_key: ${AWS_ACCESS_KEY_ID}
secret_key: ${AWS_SECRET_ACCESS_KEY}
region: ${AWS_REGION:-us-east-1}
- name: mock
type: mock
routes:
- id: gpt-route # unique route ID
model: "gpt*" # glob pattern for model matching
provider: openai # single-provider shorthand
- id: claude-balanced
model: "claude*"
strategy: weighted # model-prefix (default), round-robin, weighted
providers:
- provider: anthropic
weight: 70
- provider: bedrock
weight: 30
fallback: openai # fallback provider on failure
- id: ollama-local
model: "ollama/*"
provider: ollama
api_keys:
- key: ${MY_GATEWAY_KEY} # static key from env var
tenant: production
name: prod-key
scopes: [completions:write]
- generate: true # auto-generated, printed at startup
tenant: development
name: dev-key
rate_limits:
requests_per_minute: 600
tokens_per_minute: 100000
Provider Types
type value | Description | Required fields |
|---|---|---|
openai | OpenAI API | api_key |
anthropic | Anthropic Claude | api_key |
gemini | Google Gemini | api_key |
ollama | Ollama (local) | base_url (optional) |
bedrock | AWS Bedrock | access_key, secret_key, region |
mock | Mock provider | — |
Environment Variable References
YAML values support $\{VAR\} and ${VAR:-default} syntax, resolved at startup:
providers:
- name: openai
type: openai
api_key: ${OPENAI_API_KEY} # required — fails if unset
base_url: ${OPENAI_BASE_URL:-https://api.openai.com/v1} # with default
Minimal Environment Variable Config (No YAML File)
You can configure a single provider entirely through environment variables, without creating a gateway.yaml file:
# Single provider + auto-generated API key
GATEWAY_MODE=standalone \
OPENAI_API_KEY=sk-... \
./mvnw -pl gateway-server spring-boot:run
Or with a static API key:
GATEWAY_MODE=standalone \
OPENAI_API_KEY=sk-... \
GATEWAY_API_KEY=gw_mykey123456789012345678901234567890ab \
./mvnw -pl gateway-server spring-boot:run
When providers are configured via environment variables but no gateway.yaml exists, the gateway auto-generates an API key and prints it in the startup banner.
Auto-Generated API Keys
When generate: true is set on an API key entry (or when no key is explicitly configured), the gateway generates a cryptographically secure key at startup and prints it in a banner:
╔════════════════════════════════════════════════════════╗
║ GENERATED API KEYS (gateway.yaml) ║
╠════════════════════════════════════════════════════════╣
║ dev-key (development): gw_a1b2c3d4e5f6... ║
╠════════════════════════════════════════════════════════╣
║ Save these keys! They will NOT be shown again. ║
╚════════════════════════════════════════════════════════╝
Generated keys are stored in memory and lost on restart — they are regenerated each time.
Schema Validation
On startup, the gateway validates the gateway.yaml file and produces clear error messages with field paths:
- Missing required fields:
providers[0].type is required - Invalid provider type:
providers[1].type 'unknown' is not a valid provider type - Invalid strategy:
routes[0].strategy 'random' is not valid — use model-prefix, round-robin, weighted, or latency-aware - Weighted route without weights:
routes[1] uses weighted strategy but providers have no weight
Invalid configuration logs errors at WARN level — the gateway continues startup but the misconfigured entries are skipped.
Example Files
Pre-built examples in examples/gateway-yaml/:
| File | Description |
|---|---|
gateway.full.yaml | All providers, routes, API keys, rate limits |
gateway.openai.yaml | Minimal OpenAI-only setup |
gateway.anthropic.yaml | Minimal Anthropic-only setup |
gateway.ollama.yaml | Local Ollama (no API key needed) |
gateway.multi-provider.yaml | Multiple providers with weighted routing |
Provider Activation
A provider bean is only registered when its activation condition is met:
| Provider | Activation Condition |
|---|---|
| OpenAI | OPENAI_API_KEY is set and non-blank |
| Anthropic | ANTHROPIC_API_KEY is set and non-blank |
| Gemini | GEMINI_API_KEY is set and non-blank |
| Ollama | OLLAMA_ENABLED=true |
| Bedrock | BEDROCK_ENABLED=true |
| Mock | MOCK_PROVIDER_ENABLED=true |
If no provider is configured for a requested model, the gateway returns HTTP 400 with error code no_provider.
Property Reference
gateway.providers.*
See Provider Setup for per-provider configuration details.
gateway.routes[]
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
id | string | yes | — | Unique route identifier |
model-pattern | string | yes | — | Glob pattern to match model names |
strategy | string | no | model-prefix | model-prefix, round-robin, weighted, latency-aware (enterprise) |
cost-tolerance-pct | int | no | 0 | Cost tolerance for latency-aware routing (0–100) |
providers[].provider | string | yes | — | Provider name |
providers[].weight | int | no | 1 | Weight for weighted strategy |
providers[].region | string | no | — | Region affinity for this provider entry |
pinned-model-version | string | no | — | Override model name sent to provider |
gateway.resilience.*
| Property | Type | Default | Description |
|---|---|---|---|
resilience.retry.max-attempts | int | 3 | Max retry attempts on failure |
resilience.retry.wait-duration-ms | int | 500 | Wait between retries (ms) |
resilience.circuit-breaker.failure-rate-threshold | int | 50 | Failure % to open circuit |
resilience.circuit-breaker.sliding-window-size | int | 20 | Calls in sliding window |
resilience.circuit-breaker.wait-duration-in-open-state-ms | int | 30000 | Time before half-open (ms) |
resilience.timeout.chat-timeout-ms | int | 30000 | Non-streaming request timeout |
resilience.timeout.streaming-timeout-ms | int | 120000 | Streaming request timeout |
gateway.rate-limit.*
| Property | Type | Default | Description |
|---|---|---|---|
rate-limit.enabled | boolean | false | Enable rate limiting |
rate-limit.global.requests-per-second | int | 100 | Global request cap |
rate-limit.default-per-key.requests-per-second | int | 10 | Default per-key request rate |
rate-limit.default-per-key.tokens-per-minute | int | 100000 | Default per-key token budget |
rate-limit.keys.\{key\}.* | — | — | Per-key overrides |
gateway.cache.*
| Property | Type | Default | Description |
|---|---|---|---|
cache.enabled | boolean | false | Enable response caching |
cache.ttl-seconds | int | 3600 | Cache entry time-to-live |
cache.max-size | int | 10000 | Max entries (Caffeine only) |
cache.redis.enabled | boolean | false | Use Redis instead of Caffeine |
gateway.pii.* (Enterprise — PII Detection)
| Property | Type | Default | Description |
|---|---|---|---|
pii.enabled | boolean | true | Enable PII detection and enforcement |
pii.default-action | string | LOG | Default action: LOG, BLOCK, REDACT |
pii.scan-responses | boolean | true | Scan LLM responses for PII output leaks |
pii.strip-before-cache | boolean | true | Always redact PII before writing to cache |
pii.token-encryption-password | string | — | AES-256-GCM password for PII token encryption |
pii.max-tokens-per-tenant | int | 50000 | Maximum PII tokens stored per tenant |
pii.token-retention-days | int | 30 | Days to retain PII tokens before expiry |
Per-tenant PII configuration is set via tenant metadata keys:
| Metadata Key | Values | Description |
|---|---|---|
pii.enabled | true / false | Override PII detection for this tenant |
pii.action | BLOCK / REDACT / LOG | Override default PII action for this tenant |
pii.scan-responses | true / false | Override response scanning for this tenant |
pii.custom-patterns | JSON string | Custom regex patterns ({"label": "regex", ...}) |
cost.downgrade-threshold-pct | int (0–100) | Budget utilization % at which model downgrade triggers (default: 80) |
cost.downgrade-rules | string | Comma-separated model downgrade rules (format: "from:to,from:to", e.g. "gpt-4o:gpt-4o-mini,claude-3-opus:claude-3-sonnet") |
cost.anomaly-threshold-pct | int | Per-tenant anomaly detection threshold (default: 200 = 2x baseline) |
See PII Detection for full configuration details.
gateway.guardrail.* (Enterprise — Guardrails & Safety)
| Property | Type | Default | Description |
|---|---|---|---|
guardrail.enabled | boolean | true | Enable guardrail detection and enforcement |
guardrail.default-action | string | LOG | Default action: LOG, BLOCK, FLAG |
guardrail.scan-responses | boolean | true | Scan LLM responses for violations |
guardrail.risk-score-threshold | double | 0.7 | Detections below this score are ignored |
guardrail.max-input-tokens | int | 32000 | Max estimated input tokens (OWASP LLM10) |
guardrail.max-messages-per-request | int | 100 | Max messages per request (OWASP LLM10) |
guardrail.max-message-length | int | 50000 | Max character length per message (OWASP LLM10) |
guardrail.default-max-response-tokens | int | 4096 | Applied when client doesn't specify max_tokens |
Per-tenant guardrail configuration is set via tenant metadata keys:
| Metadata Key | Values | Description |
|---|---|---|
guardrail.enabled | true / false | Override guardrail detection for this tenant |
guardrail.action | BLOCK / FLAG / LOG | Override default action for this tenant |
guardrail.risk-score-threshold | double (0.0–1.0) | Override risk score threshold |
guardrail.max-input-tokens | int | Override max estimated input tokens |
guardrail.max-messages-per-request | int | Override max messages per request |
guardrail.max-message-length | int | Override max message character length |
guardrail.default-max-response-tokens | int | Override default response token cap |
guardrail.content.profanity.action | BLOCK / FLAG / LOG | Per-category action override |
guardrail.content.violence.action | BLOCK / FLAG / LOG | Per-category action override |
guardrail.content.sexual.action | BLOCK / FLAG / LOG | Per-category action override |
guardrail.content.competitor.keywords | comma-separated | Competitor brand keywords |
guardrail.content.topic-restrictions | comma-separated | Restricted topic keywords |
guardrail.content.custom-denylist | JSON string | Custom deny-list patterns |
guardrail.injection.custom-patterns | JSON string | Custom injection patterns |
guardrail.mcp-injection.enabled | true / false | Enable MCP injection scanning |
guardrail.mcp-injection.action | BLOCK / FLAG / SANITIZE | MCP injection action |
guardrail.context.warning-threshold-pct | int (0–100) | Context window warning threshold (default: 70) |
guardrail.context.hard-threshold-pct | int (0–100) | Context window hard threshold (default: 90) |
guardrail.context.pruning-strategy | NONE / TRUNCATE_OLDEST / TRUNCATE_MIDDLE | Context pruning strategy |
See Guardrails & Safety for full configuration details.
gateway.finops.* (Enterprise — Cost Calculation)
| Property | Type | Default | Description |
|---|---|---|---|
finops.enabled | boolean | true | Enable enterprise cost calculation |
finops.pricing-cache-ttl-seconds | int | 60 | TTL for pricing lookup cache (0 = disabled) |
finops.spend-cache-ttl-seconds | int | 5 | TTL for budget spend cache (avoids per-request DB queries) |
finops.soft-alert-cooldown-minutes | int | 60 | Cooldown between soft budget alert audit events |
finops.downgrade-cache-ttl-seconds | int | 5 | TTL for per-tenant downgrade policy cache (0 = disabled) |
finops.chargeback-schedule | string | "" | Cron expression for monthly chargeback report auto-generation (empty = disabled) |
finops.anomaly-threshold-pct | int | 200 | Default anomaly threshold: current daily rate vs 30d baseline (200 = 2x) |
finops.budget-warning-threshold-pct | int | 75 | Default utilization % threshold for WARN_AGENT policy rules |
Cost calculation uses ModelPricing entries managed via the /admin/v1/pricing API. Pricing supports glob patterns (e.g. gpt-4o* matches gpt-4o, gpt-4o-mini). Costs are calculated per-request using BigDecimal precision and persisted as CostRecord entries, queryable via /admin/v1/costs.
Budget caps enforce soft and hard spending limits per tenant, API key, or globally. Configure budgets via /admin/v1/budgets. Soft limits trigger BUDGET_CAP_SOFT audit events at a configurable threshold (default 80%). Hard limits block requests with HTTP 402 and write BUDGET_CAP_HARD audit events. Budget periods (DAILY, WEEKLY, MONTHLY) reset automatically at UTC boundaries.
Chargeback reports aggregate costs by tenant, API key, model, provider, and time period. Reports are exportable as CSV and PDF. Monthly auto-generation is available via chargeback-schedule cron. Cost forecasting uses trailing 7-day and 30-day spend trends with linear projection. Cost anomaly detection compares current daily spend rate against the 30-day baseline; alerts fire when the deviation exceeds the configured threshold (per-tenant override via cost.anomaly-threshold-pct metadata key).
Enterprise Config Sync (Multi-Instance)
Requires enterprise-core on classpath + valid JWT license key. Enables instances to poll a primary instance for configuration changes within 5 seconds.
| Property | Environment Variable | Default | Description |
|---|---|---|---|
gateway.config.sync.enabled | — | false | Enable config polling on secondary instances |
gateway.config.sync.control-plane-url | — | — | Base URL of the primary instance (e.g. http://dvara-primary:8080) |
gateway.config.sync.poll-interval-ms | — | 3000 | How often to check for version changes (ms) |
gateway.config.sync.internal-secret | — | — | Shared secret for /internal/* API authentication |
gateway.config.sync.connect-timeout-ms | — | 3000 | HTTP connect timeout for control plane calls |
gateway.config.sync.read-timeout-ms | — | 5000 | HTTP read timeout for control plane calls |
gateway.config.sync.heartbeat-interval-ms | — | 10000 | How often to POST heartbeat to control plane (ms) |
Secondary instances check /internal/v1/config/version every poll-interval-ms. On version change, the full config is fetched from /internal/v1/config/full and applied locally. Instances also POST heartbeats to /internal/v1/instances/heartbeat for fleet visibility.
Enterprise Latency-Aware Routing Configuration
Requires enterprise-routing on classpath + valid JWT license key.
| Property | Environment Variable | Default | Description |
|---|---|---|---|
gateway.routing.latency.alpha | — | 0.2 | EWMA smoothing factor (0.0–1.0). Higher values give more weight to recent samples |
gateway.routing.latency.decay-threshold-ms | — | 60000 | Staleness threshold in milliseconds. Entries older than this receive a decay penalty |
gateway.routing.latency.decay-multiplier | — | 0.5 | Stale EWMA is divided by this value (lower = harsher penalty) |
gateway.routing.latency.min-samples | — | 5 | Minimum latency samples before EWMA is used for routing decisions |
gateway.routing.latency.snapshot-interval | — | 100 | Persist latency snapshot to repository every N samples |
Enterprise Priority Routing Configuration
Requires enterprise-routing on classpath + valid JWT license key.
| Property | Environment Variable | Default | Description |
|---|---|---|---|
gateway.routing.priority.enabled | — | false | Enable concurrency-based priority admission control |
gateway.routing.priority.max-concurrent-requests | — | 1000 | Maximum concurrent requests across all tiers |
gateway.routing.priority.tiers.premium.throttle-threshold-pct | — | 100 | Load % at which premium requests are throttled |
gateway.routing.priority.tiers.standard.throttle-threshold-pct | — | 80 | Load % at which standard requests are throttled |
gateway.routing.priority.tiers.bulk.throttle-threshold-pct | — | 50 | Load % at which bulk requests are throttled |
gateway.routing.priority.resolver-cache-ttl-seconds | — | 5 | TTL for tenant → priority tier cache |
Enterprise Webhook Configuration
Requires enterprise-audit on classpath + valid JWT license key.
| Property | Environment Variable | Default | Description |
|---|---|---|---|
gateway.webhooks.enabled | GATEWAY_WEBHOOKS_ENABLED | true | Enable webhook delivery of governance events |
gateway.webhooks.max-retries | GATEWAY_WEBHOOKS_MAX_RETRIES | 3 | Maximum retry attempts for failed deliveries |
gateway.webhooks.base-retry-delay-ms | GATEWAY_WEBHOOKS_RETRY_DELAY | 1000 | Base delay in milliseconds for exponential backoff |
gateway.webhooks.retry-multiplier | GATEWAY_WEBHOOKS_RETRY_MULTIPLIER | 4 | Multiplier for exponential backoff (delay = base x multiplier^attempt) |
gateway.webhooks.delivery-timeout-ms | GATEWAY_WEBHOOKS_DELIVERY_TIMEOUT | 5000 | HTTP connect+read timeout for webhook delivery |
gateway.webhooks.approval-base-url | GATEWAY_WEBHOOKS_APPROVAL_BASE_URL | "" (empty) | Base URL for approve/deny links in MCP approval webhooks |
gateway.webhooks.approval-ttl-minutes | GATEWAY_WEBHOOKS_APPROVAL_TTL | 15 | TTL in minutes for approval token validity |
gateway.persistence.* (Enterprise — Database Persistence)
Requires enterprise-persistence on classpath + valid JWT license key.
| Property | Environment Variable | Default | Description |
|---|---|---|---|
gateway.persistence.enabled | GATEWAY_PERSISTENCE_ENABLED | false | Enable database-backed persistence for all repositories |
gateway.persistence.batch-size | GATEWAY_PERSISTENCE_BATCH_SIZE | 100 | Batch size for bulk write operations |
spring.datasource.url | SPRING_DATASOURCE_URL | — | JDBC connection URL (e.g. jdbc:postgresql://localhost:5432/dvara) |
spring.datasource.username | SPRING_DATASOURCE_USERNAME | — | Database username |
spring.datasource.password | DB_PASSWORD | — | Database password |
spring.flyway.enabled | SPRING_FLYWAY_ENABLED | true | Auto-run Flyway database migrations on startup |
# Enterprise Persistence (enterprise-persistence module)
gateway:
persistence:
enabled: true # default: false
batch-size: 100 # default: 100
spring:
datasource:
url: jdbc:postgresql://localhost:5432/dvara
username: dvara
password: ${DB_PASSWORD}
flyway:
enabled: true # auto-runs migrations on startup
gateway.caching.* (Enterprise — Distributed Caching)
Requires enterprise-caching on classpath + valid JWT license key.
| Property | Environment Variable | Default | Description |
|---|---|---|---|
gateway.caching.distributed.enabled | GATEWAY_CACHING_DISTRIBUTED_ENABLED | false | Enable Redis cache-aside decorators for repositories |
gateway.caching.distributed.ttl-seconds | GATEWAY_CACHING_DISTRIBUTED_TTL | 300 | Default cache TTL in seconds |
gateway.caching.distributed.max-entries | GATEWAY_CACHING_DISTRIBUTED_MAX_ENTRIES | 10000 | Maximum cache entries |
gateway.caching.distributed.key-prefix | GATEWAY_CACHING_DISTRIBUTED_KEY_PREFIX | dvara | Redis key prefix for all cache entries |
gateway.ratelimit.distributed.enabled | GATEWAY_RATELIMIT_DISTRIBUTED_ENABLED | false | Enable Redis sliding-window distributed rate limiter |
spring.data.redis.host | SPRING_DATA_REDIS_HOST | localhost | Redis server hostname |
spring.data.redis.port | SPRING_DATA_REDIS_PORT | 6379 | Redis server port |
spring.data.redis.password | REDIS_PASSWORD | — | Redis server password |
# Enterprise Distributed Caching (enterprise-caching module)
gateway:
caching:
distributed:
enabled: true # default: false
ttl-seconds: 300
max-entries: 10000
key-prefix: dvara
ratelimit:
distributed:
enabled: true # default: false (Redis sliding-window)
spring:
data:
redis:
host: localhost
port: 6379
password: ${REDIS_PASSWORD:}
MCP Proxy Configuration
Configuration for the standalone MCP Proxy application (mcp-proxy-server, port 8070). Requires enterprise license.
| Property | Environment Variable | Default | Description |
|---|---|---|---|
gateway.mcp.timeout-default | MCP_TIMEOUT_DEFAULT | 30 | Default timeout in seconds for MCP server requests |
gateway.mcp.timeout-max | MCP_TIMEOUT_MAX | 120 | Maximum allowed timeout in seconds |
gateway.mcp.registry-cache-ttl-seconds | MCP_REGISTRY_CACHE_TTL | 30 | TTL for the Caffeine-backed MCP server registry cache |
gateway.mcp.registry-cache-max-size | MCP_REGISTRY_CACHE_MAX_SIZE | 1000 | Maximum entries in the MCP server registry cache |
management.* (Observability)
| Property | Type | Default | Description |
|---|---|---|---|
management.endpoints.web.exposure.include | string | health,prometheus,gateway-status | Actuator endpoints to expose |
management.endpoint.health.show-details | string | when-authorized | Health detail visibility |
management.prometheus.metrics.export.enabled | boolean | true | Enable Prometheus scrape endpoint |
Logging
| Configuration | Value | Description |
|---|---|---|
| Default format | JSON (LogstashEncoder) | Every log line is valid JSON |
| Plain-text mode | spring.profiles.active=log-plain | Human-readable output for local dev |
| Log config file | logback-spring.xml | Logback configuration with Spring profile support |