This guide provides detailed instructions for configuring Otto Config with AWS services.
AWS AppConfig provides validated configuration deployment with rollback capabilities.
Use the provided Terraform module to provision AppConfig resources:
module "appconfig_service" {
source = "https://github.com/otto-de/otto-config.git//terraform"
service = "my-service"
toggles_configuration_content = file("${path.module}/appconfig_toggles.json")
properties_configuration_content = file("${path.module}/appconfig_properties.json")
# Optional: enable event-driven refresh via EventBridge → SQS
change_notification_enabled = true
}{
"properties": {
"database.url": "jdbc:postgresql://prod-db:5432/myapp",
"database.pool.size": "20",
"feature.search.enabled": "true",
"cache.timeout": "3600",
"api.endpoint": "https://api.example.com"
}
}{
"flags": {
"new_feature": { "name": "NEW_FEATURE" },
"logging_enabled": { "name": "LOGGING_ENABLED" },
"beta_ui": { "name": "BETA_UI" }
},
"values": {
"new_feature": { "enabled": true },
"logging_enabled": { "enabled": false },
"beta_ui": { "enabled": false }
},
"version": "1"
}Enable AppConfig sources in your application.properties:
otto.config.sources.enabled=aws.appconfig.properties,aws.appconfig.togglesVersion: '2012-10-17'
Statement:
- Effect: Allow
Action:
- appconfig:StartConfigurationSession
- appconfig:GetLatestConfiguration
Resource: "*"- Use deployment strategies to gradually roll out changes
- Set up validators to prevent invalid configurations from being deployed
- Use environments (dev, staging, prod) to separate configurations
- Monitor deployment status and rollback if issues occur
AWS Secrets Manager stores encrypted secrets with automatic rotation support.
Specify one or more secret ARNs in your application properties:
# Single secret
otto.config.aws.secrets.arn=arn:aws:secretsmanager:us-east-1:123456789012:secret:my-app-secrets
# Multiple secrets (comma-separated)
otto.config.aws.secrets.arn=arn:aws:secretsmanager:us-east-1:123456789012:secret:app-secrets,arn:aws:secretsmanager:us-east-1:123456789012:secret:db-credentialsEnable the source:
otto.config.sources.enabled=aws.secretsSecrets should be stored as JSON key-value pairs:
{
"database.password": "supersecret123",
"api.key": "abc123xyz789",
"jwt.secret": "jwt-signing-key"
}Otto Config supports accessing previous versions of secrets:
// Current version
String currentPassword = configurationProvider.getValue("database.password");
// Previous version (for rotation scenarios)
@PropertyValue("database.password")
private PropertyVersion databasePassword;
String current = databasePassword.getCurrent().get();
String previous = databasePassword.getPrevious().get();Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- secretsmanager:GetSecretValue
- secretsmanager:ListSecrets
- secretsmanager:DescribeSecret
- secretsmanager:BatchGetSecretValue
Resource: "*"- Never hardcode secrets in your application code
- Use automatic rotation for database credentials
- Enable versioning to support credential rotation without downtime
- Use resource-based policies to restrict access
- Monitor secret access via CloudTrail
AWS Systems Manager Parameter Store provides hierarchical configuration storage.
Specify one or more path prefixes:
# Single path
otto.config.aws.ssm.path.prefix=/my-app/config
# Multiple paths (comma-separated)
otto.config.aws.ssm.path.prefix=/my-app/config,/shared/config
# Load all accessible parameters (not recommended for production)
# otto.config.aws.ssm.path.prefix=Enable the source:
otto.config.sources.enabled=aws.ssmUse hierarchical paths for organization:
/my-app/
/config/
/database/
url
pool-size
/api/
endpoint
timeout
/features/
search-enabled
beta-ui
Otto Config normalizes parameter names:
/my-app/config/database/url→database.url- Both formats can be used to access the value
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- ssm:GetParametersByPath
- ssm:GetParameter
- ssm:GetParameters
Resource:
- "arn:aws:ssm:*:*:parameter/my-app/*"- Use hierarchical paths for organization
- Apply least privilege IAM policies with specific path restrictions
- Use SecureString type for sensitive data
- Tag parameters for cost tracking and governance
- Use parameter policies for expiration and change notifications
Hashicorp Vault provides enterprise-grade secret management.
# Vault server URL
otto.config.hashicorp.vault.url=https://vault.example.com:8200
# Secret paths (comma-separated)
otto.config.hashicorp.vault.path=/secret/my-app,/secret/shared
# Number of previous versions to load (default: 1)
otto.config.hashicorp.vault.prev.versions=2Enable the source:
otto.config.sources.enabled=hashicorp.vaultotto.config.hashicorp.vault.auth.approle.role.id=${VAULT_ROLE_ID}
otto.config.hashicorp.vault.auth.approle.secret.id=${VAULT_SECRET_ID}Always use environment variables for credentials, never hardcode them.
otto.config.hashicorp.vault.auth.type=aws
otto.config.hashicorp.vault.auth.aws.region=${AWS_REGION}
otto.config.hashicorp.vault.auth.aws.role.name=my-app-role
otto.config.hashicorp.vault.auth.aws.role.arn=${AWS_ROLE_ARN}
otto.config.hashicorp.vault.auth.aws.header.value=vault.example.comVault secrets support versioning. Access previous versions:
@PropertyValue("database.password")
private PropertyVersion password;
String current = password.getCurrent().get();
String previous = password.getPrevious().get();
List<String> allVersions = password.getVersions();- Use namespaces to isolate different applications
- Enable audit logging to track secret access
- Configure lease durations appropriate for your use case
- Use dynamic secrets for database credentials when possible
- Implement secret rotation policies
Instead of polling every 5 minutes, Otto Config can receive immediate notifications when configuration changes.
- EventBridge rules detect changes in AppConfig, Secrets Manager, and Parameter Store
- Events are sent to an SQS queue
- Otto Config polls the queue and refreshes configuration immediately
module "appconfig_service" {
source = "https://github.com/otto-de/otto-config.git//terraform"
service = "my-service"
# ... other configuration ...
change_notification_enabled = true
}This creates:
- SQS queue for change notifications
- EventBridge rules for AppConfig, Secrets Manager, and SSM changes
- Required IAM permissions
Use the change_notification_queue_url output from Terraform:
otto.config.aws.change.notifications.enabled=true
otto.config.aws.change.notifications.queue.url=https://sqs.us-east-1.amazonaws.com/123456789012/otto-config-changesVersion: '2012-10-17'
Statement:
- Effect: Allow
Action:
- sqs:ReceiveMessage
- sqs:DeleteMessage
- sqs:GetQueueAttributes
Resource: "arn:aws:sqs:*:*:otto-config-changes"- Immediate updates: Configuration changes take effect within seconds, not minutes
- Reduced API calls: Less frequent polling of AWS services
- Cost savings: Fewer API requests to AWS services
- Better responsiveness: Critical configuration changes propagate faster
Monitor the SQS queue:
- ApproximateNumberOfMessages: Should stay near zero if consumption is healthy
- ApproximateAgeOfOldestMessage: Should be low (< 30 seconds)
- NumberOfMessagesSent: Indicates configuration change frequency
When running in multiple AWS regions:
- AppConfig: Create applications in each region
- Secrets Manager: Replicate secrets across regions
- Parameter Store: Copy parameters to each region
- Event Notifications: Set up SQS queues in each region
- Use IAM roles instead of access keys whenever possible
- Apply least privilege - grant only necessary permissions
- Enable encryption for Secrets Manager and Parameter Store
- Use VPC endpoints to keep traffic within AWS network
- Enable CloudTrail logging for audit trails
- Rotate credentials regularly
- Use resource policies to restrict access
- Tag resources for governance and cost tracking
- AppConfig: Charged per configuration request
- Secrets Manager: $0.40/secret/month + $0.05/10,000 API calls
- Parameter Store: Standard parameters are free, advanced parameters are $0.05/parameter/month
- SQS: First 1M requests/month free
Tips:
- Use Parameter Store standard parameters for non-sensitive config (free)
- Set appropriate refresh intervals (default 5 minutes is reasonable)
- Use event-driven refresh to reduce polling frequency
- Share secrets across applications when appropriate
- Check IAM permissions
- Verify resource ARNs/paths are correct
- Enable DEBUG logging:
logging.level.de.otto.config=DEBUG - Check CloudWatch Logs for error messages
- Check network latency to AWS services
- Consider using VPC endpoints
- Enable event-driven refresh for immediate updates
- Review the number of configuration sources
- Verify AWS credentials are configured
- Check IAM role/user has necessary permissions
- For Vault, ensure role_id and secret_id are valid
- Check security group rules for Vault connectivity