Skip to main content

Managing Configurations

WSO2 Integrator uses Ballerina's configuration system to externalize runtime settings. This page covers strategies for managing configurations across development, testing, staging, and production environments.

Configuration sources

Ballerina resolves configuration values from multiple sources, with the following precedence (highest first):

PrioritySourceExample
1Command-line arguments--myModule.port=9090
2Environment variablesBAL_MY_MODULE_PORT=9090
3Config.toml file(s)[myModule] port = 9090
4Default values in codeconfigurable int port = 8080;

Defining configurable values

Declare configurable variables in your Ballerina code:

configurable int port = 8080;
configurable string dbHost = "localhost";
configurable string dbName = "orders";
configurable string dbUser = ?; // Required -- no default
configurable string dbPassword = ?; // Required -- no default

Per-Environment config files

Directory structure

Organize configuration files by environment:

my-integration/
src/
main.bal
Ballerina.toml
Config.toml # Default / local development
config/
dev/
Config.toml # Development environment
test/
Config.toml # Test environment
staging/
Config.toml # Staging environment
prod/
Config.toml # Production environment

Development config

config/dev/Config.toml:

port = 9090

[db]
host = "dev-db.internal.example.com"
name = "orders_dev"
user = "dev_user"
password = "dev_password"

[logging]
level = "DEBUG"

Production config

config/prod/Config.toml:

port = 9090

[db]
host = "prod-db.internal.example.com"
name = "orders"
user = "svc_orders"
password = "encrypted:xxxxxx"

[logging]
level = "INFO"

Selecting the config file at runtime

Use the BAL_CONFIG_FILES environment variable:

# Use dev config
BAL_CONFIG_FILES=config/dev/Config.toml bal run

# Use production config
BAL_CONFIG_FILES=config/prod/Config.toml java -jar my_integration.jar

Supply multiple config files (merged in order, later files override earlier):

BAL_CONFIG_FILES=config/base/Config.toml:config/prod/Config.toml java -jar my_integration.jar

Environment variable overrides

Override any configurable value using environment variables. The naming convention is:

BAL_<MODULE>_<VARIABLE> (all uppercase, dots replaced with underscores)
export BAL_DB_HOST="prod-db.internal.example.com"
export BAL_DB_PASSWORD="s3cur3p@ss"
java -jar my_integration.jar

This is useful for container orchestrators and CI/CD pipelines.

Kubernetes ConfigMaps and secrets

ConfigMap for Non-Sensitive values

apiVersion: v1
kind: ConfigMap
metadata:
name: integration-config
data:
Config.toml: |
port = 9090

[db]
host = "db.internal.svc.cluster.local"
name = "orders"
user = "svc_orders"

[logging]
level = "INFO"

Secret for sensitive values

apiVersion: v1
kind: Secret
metadata:
name: integration-secrets
type: Opaque
stringData:
BAL_DB_PASSWORD: "s3cur3p@ss"
BAL_API_KEY: "ak_xxxxxxxxxxxxx"

Mount in deployment

containers:
- name: integration
image: myorg/my-integration:1.0.0
env:
- name: BAL_CONFIG_FILES
value: /config/Config.toml
envFrom:
- secretRef:
name: integration-secrets
volumeMounts:
- name: config-volume
mountPath: /config
volumes:
- name: config-volume
configMap:
name: integration-config

Consolidated Multi-Service configuration

When running multiple integrations in a consolidated package, namespace each service's config:

# Shared settings
[http]
maxConnections = 100

# Order Service
[order_service.db]
host = "db.internal.example.com"
name = "orders"

[order_service.http]
port = 9091

# Inventory Service
[inventory_service.db]
host = "db.internal.example.com"
name = "inventory"

[inventory_service.http]
port = 9092

# Notification Service
[notification_service.smtp]
host = "smtp.example.com"
port = 587

Configuration encryption

Encrypt sensitive values in Config.toml:

bal encrypt
Enter value: <type the secret>
Enter secret: <type the encryption key>
Encrypted value: encrypted:aBcDeFgHiJkLmNoPqRsTuV==

Use the encrypted value in Config.toml:

[db]
password = "encrypted:aBcDeFgHiJkLmNoPqRsTuV=="

At runtime, provide the decryption key:

BAL_CONFIG_SECRET_KEY=my-secret-key java -jar my_integration.jar

Configuration validation

Ballerina validates configurations at startup. If a required configurable has no value, the application fails to start with a clear error:

error: value not provided for required configurable variable 'dbPassword'

Use constrained types to enforce valid values:

configurable int port = 8080;    // Must be an integer
configurable string dbHost = ?; // Required string
configurable "DEBUG"|"INFO"|"WARN"|"ERROR" logLevel = "INFO"; // Enum constraint

Best practices

PracticeDescription
Never commit secretsKeep Config.toml with secrets out of version control
Use .gitignoreAdd config/prod/Config.toml to .gitignore
Validate earlyUse required configurables (= ?) for mandatory settings
Layer configsUse base + environment-specific files for DRY configuration
Prefer env vars for secretsUse environment variables for passwords and API keys in CI/CD

What's next