目次
AWS AppConfig 完全ガイド v2.0
フィーチャーフラグ・設定管理・段階的ロールアウト
AWS AppConfig は、「アプリケーション設定(フィーチャーフラグ・設定値)を安全にデプロイ・動的に更新するサービスで、段階的ロールアウト(Canary・Linear)・バリデーション(JSON Schema・Lambda)・自動ロールバック(CloudWatch アラーム連携)を実現するサービス」 です。コードのデプロイなしにアプリの動作を変更でき、問題発生時は即座にフラグをオフにして影響を局所化できます。本ドキュメントは初心者から実務者向けに、フィーチャーフラグ・設定管理・デプロイ戦略・2025-2026 動向を体系的に解説する包括的ガイドです。
ドキュメントの目的
本ガイドは以下を対象としています。
- 初心者向け: AppConfig とは何か、フィーチャーフラグの基本を学びたい方
- 開発者向け: フィーチャーフラグ・動的設定をアプリに組み込みたい方
- SRE/DevOps 向け: 段階的ロールアウト・自動ロールバック・設定バリデーション
- 意思決定者向け: AppConfig vs LaunchDarkly vs Unleash の選定
2025-2026 年の AppConfig エコシステム
- Enhanced Targeting(2026年3月): ユーザーセグメンテーション・属性ベースのフラグ制御
- CloudWatch Evidence 統合: A/B テスト結果の自動分析・推奨値提示
- AppConfig Agent Lambda Extension: キャッシング・オフライン対応の強化
- ML 駆動 Anomaly Detection: メトリクス異常自動検知でロールバック自動化
- Secrets Manager 統合: 設定値と秘密情報の統一管理
目次
- 概要
- AppConfig が解決する課題
- 主な特徴
- アーキテクチャ
- コアコンポーネント
- フィーチャーフラグの設定
- デプロイ戦略
- バリデーター
- 主要ユースケース
- 設定・操作の具体例
- 類似サービス比較表
- ベストプラクティス
- トラブルシューティング
- 2025-2026 最新動向
- 学習リソース・参考文献
- 実装例
- チェックリスト
- まとめ
概要
初心者向けメモ: AppConfig は「新機能をオン/オフしたい」「リリース前にごく少数(1%)に試したい」「問題が発生したら即座にオフにしたい」という要件をシンプルに実現するサービスです。通常は機能フラグライブラリ(LaunchDarkly・Unleash)を使いますが、AppConfig は AWS ネイティブで、CloudWatch アラームによる自動ロールバックが標準装備。AWS 環境では AppConfig で十分な場合が多いです。
AWS AppConfig 公式定義:
“AWS AppConfig feature flags and dynamic configurations help software builders quickly and securely adjust application behavior in production environments without full code deployments.”
このサービスを選ぶ理由
なぜ AppConfig でないといけないのか?
| 理由 | 詳細 |
|---|---|
| コードデプロイなしの機能制御 | フィーチャーフラグのオン/オフで新機能リリース、問題発生時は即座にオフ |
| 段階的ロールアウト | 全体リリース前に 10% → 25% → 50% → 100% と段階的に展開し問題を早期検知 |
| 自動ロールバック | CloudWatch アラームがエラー率・レイテンシ閾値を超過したら自動的に前バージョンに復元 |
| AWS ネイティブ統合 | IAM・KMS・CloudWatch・Secrets Manager と完全統合、追加ツール不要 |
| コスト最適化 | LaunchDarkly($75/月~)より圧倒的に安い、API 呼び出し単位の従量課金 |
具体的なユースケース
- 新機能の段階的リリース(Beta ユーザー → 10% → 全体のフィーチャーフラグ制御)
- 緊急メンテナンス時の機能無効化(コードデプロイなしにリクエスト受付をオフ)
- A/B テストのフラグ管理(アルゴリズム A vs B の出し分け制御)
- Lambda 関数の動的設定更新(環境変数変更なしにパラメーター値をホットアップデート)
- アプリケーションのレート制限値を動的変更(負荷状況に応じたスロットリング調整)
AppConfig が解決する課題
| 課題 | 従来(コードデプロイ) | AppConfig 解決方法 |
|---|---|---|
| 新機能リリース時間 | 本番デプロイに 30 分~数時間 | フラグ設定で即座リリース(数分) |
| ロールバック | コード修正 → テスト → デプロイで数時間 | フラグ OFF で即座ロールバック |
| 段階的テスト | Staging 環境でテスト後に本番デプロイ | Canary・Linear 戦略で本番ユーザーの 1% でテスト |
| 緊急対応 | コードデプロイ待機 | フラグ OFF で即座に対応 |
| A/B テスト | ロードバランサーレベルでの振り分け | AppConfig フラグで アルゴリズム振り分け |
| 複数環境の同期 | 本番・ステージング・開発の設定がズレる | AppConfig で統一管理 |
| 設定ミス検出 | 本番で初めて検出(ダウンタイム) | JSON Schema バリデーションで事前防止 |
主な特徴
1. フィーチャーフラグ管理
Flag と Attribute
- Flag:有効/無効の binary 切り替え
- Attribute:フラグの詳細設定(色、モデルバージョン等)
Flag Definition
{
"flags": {
"new-checkout": {
"name": "New Checkout Flow",
"description": "Enable redesigned checkout UI"
},
"ai-recommendations": {
"name": "AI Product Recommendations",
"attributes": {
"model-version": {
"constraints": {
"type": "string",
"enum": ["v1", "v2", "v3"]
}
}
}
}
},
"values": {
"new-checkout": { "enabled": true },
"ai-recommendations": {
"enabled": true,
"model-version": "v2"
}
}
}
2. デプロイ戦略
Immediate
- 即時全体に適用
- テスト環境向け
Linear N% every M minutes
- N% のトラフィックに展開、M 分ごとに増加
- 例:Linear 10% every 10 minutes = 10分ごとに 10% ずつ増加
Canary N% for M minutes
- N% に展開して M 分監視、問題なければ 100%
- 例:Canary 10% for 20 minutes = 10% で 20 分監視後 100%
3. バリデーター
JSON Schema
- 設定値の型・範囲・形式を事前検証
- デプロイ時に自動チェック
Lambda Validator
- カスタムロジックで複雑な検証
- DB アクセス・API 呼び出し可能
4. 自動ロールバック
CloudWatch Alarms
- エラー率・レイテンシ・カスタムメトリクス監視
- 閾値超過で自動的に前バージョンに復元
アーキテクチャ
graph TD
A["Application"]
B["AppConfig Agent<br/>Lambda Extension / EC2 Process"]
C["AWS AppConfig"]
subgraph AppConfig_Resources["AppConfig Resources"]
D["Application"]
E["Environment<br/>Production / Staging / Dev"]
F["Configuration Profile<br/>Feature Flags / Freeform"]
G["Deployment Strategy<br/>Immediate / Linear / Canary"]
end
subgraph Validation["Validation & Monitoring"]
H["Validator<br/>JSON Schema / Lambda"]
I["CloudWatch Alarms<br/>Rollback Trigger"]
end
subgraph DataSource["Configuration Source"]
J["AppConfig Hosted Config"]
K["SSM Parameter Store"]
L["Secrets Manager"]
M["S3"]
end
A -->|1. Poll Config| B
B -->|2. Cache Locally<br/>Port 2772| A
B -->|3. Get Latest| C
C --> D
D --> E
E --> F
F --> G
G --> H
H -->|4. Validate| I
I -->|5. Store| J
I -->|6. Reference| K
I -->|7. Reference| L
I -->|8. Reference| M
style A fill:#e6f3ff
style AppConfig_Resources fill:#fff0e6
style Validation fill:#ffe6e6
style DataSource fill:#e6ffe6
コアコンポーネント
1. Application(アプリケーション)
AppConfig リソースの最上位。複数の Environment を管理します。
aws appconfig create-application \
--name my-app \
--description "My Application"
2. Environment(環境)
本番・ステージング・開発など環境ごとの分離。
aws appconfig create-environment \
--application-id my-app \
--name production \
--description "Production environment"
3. Configuration Profile(設定プロファイル)
フィーチャーフラグ・設定データの定義。
2 つのタイプ
- Feature Flags: On/Off とその属性
- Freeform: JSON・YAML・テキスト自由形式
4. Deployment Strategy(デプロイ戦略)
段階的ロールアウトのルール定義。
aws appconfig create-deployment-strategy \
--name canary-10-percent-5-minutes \
--deployment-duration-in-minutes 5 \
--final-bake-time-in-minutes 10 \
--growth-factor 10.0 \
--growth-type Exponential
フィーチャーフラグの設定
フラグ定義(AppConfig Hosted Config)
{
"flags": {
"new-checkout-flow": {
"name": "New Checkout Flow",
"description": "Enable the redesigned checkout experience"
},
"ai-recommendations": {
"name": "AI Product Recommendations",
"description": "ML-driven product suggestions",
"attributes": {
"model-version": {
"description": "Model version",
"constraints": {
"type": "string",
"enum": ["v1", "v2", "v3"]
}
},
"max-recommendations": {
"description": "Maximum number of recommendations",
"constraints": {
"type": "number",
"minimum": 1,
"maximum": 20
}
}
}
},
"beta-payment-gateway": {
"name": "Beta Payment Gateway",
"description": "Test new payment provider"
}
},
"values": {
"new-checkout-flow": {
"enabled": true
},
"ai-recommendations": {
"enabled": true,
"model-version": "v2",
"max-recommendations": 5
},
"beta-payment-gateway": {
"enabled": false
}
},
"version": "1"
}
JSON Schema バリデーター
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"flags": {
"type": "object",
"patternProperties": {
"^[a-z0-9\\-]+{{CONTENT}}quot;: {
"type": "object",
"properties": {
"name": { "type": "string" },
"description": { "type": "string" }
},
"required": ["name"]
}
}
},
"values": {
"type": "object"
}
},
"required": ["flags", "values"]
}
デプロイ戦略
1. Immediate(即時)
aws appconfig create-deployment-strategy \
--name immediate \
--deployment-duration-in-minutes 0 \
--final-bake-time-in-minutes 0 \
--growth-factor 100.0
用途
- 開発・テスト環境
- 緊急で全体に展開する必要があるとき
2. Linear(線形増加)
aws appconfig create-deployment-strategy \
--name linear-50-percent-every-30-seconds \
--deployment-duration-in-minutes 1 \
--growth-factor 50.0 \
--growth-type Linear
展開例
- 0 秒:50%
- 30 秒:100%
3. Canary(カナリア)
aws appconfig create-deployment-strategy \
--name canary-10-percent-5-minutes \
--deployment-duration-in-minutes 5 \
--final-bake-time-in-minutes 10 \
--growth-factor 10.0 \
--growth-type Exponential
展開例
- 0 分:10% に展開
- 5 分:問題なければ 100%
- さらに 10 分監視
| 項目 | 説明 |
|---|---|
| deployment-duration-in-minutes | デプロイ所要時間(段階的展開の期間) |
| final-bake-time-in-minutes | 最終段階での監視時間 |
| growth-factor | 1 ステップでの増加率(%) |
| growth-type | Linear / Exponential |
バリデーター
JSON Schema バリデーター
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"rate-limit": {
"type": "integer",
"minimum": 1,
"maximum": 10000
},
"timeout-ms": {
"type": "integer",
"minimum": 100,
"maximum": 30000
}
},
"required": ["rate-limit"]
}
Lambda バリデーター
import json
def lambda_handler(event, context):
"""
AppConfig Validator function
Configuration が正しいか検証
"""
config = json.loads(event.get('configuration', '{}'))
# カスタム検証ロジック
errors = []
# rate-limit は 1~10000 の範囲
rate_limit = config.get('rate-limit')
if not isinstance(rate_limit, int) or rate_limit < 1 or rate_limit > 10000:
errors.append('rate-limit must be 1-10000')
# timeout-ms は rate-limit より大きい必要
timeout_ms = config.get('timeout-ms')
if timeout_ms and timeout_ms <= rate_limit:
errors.append('timeout-ms must be greater than rate-limit')
if errors:
return {
'statusCode': 400,
'body': json.dumps({'errors': errors})
}
return {
'statusCode': 200,
'body': json.dumps({'valid': True})
}
主要ユースケース
1. 新機能の段階的リリース
シナリオ
- チェックアウト流れを新しいUIに変更
- Beta ユーザーで 1 日テスト → 10% に展開 → 50% → 100%
実装
# フラグ作成
aws appconfig create-configuration-profile \
--application-id my-app-id \
--name new-checkout \
--description "New checkout flow" \
--type FEATURE_FLAGS
# Canary デプロイ開始(10% で 5 分)
aws appconfig start-deployment \
--application-id my-app-id \
--environment-id prod-env-id \
--deployment-strategy-id canary-10-percent-5-minutes \
--configuration-profile-id new-checkout-id \
--configuration-version 1
2. 緊急メンテナンス時の機能無効化
シナリオ
- DB メンテナンス中、新規注文受付を停止
- コードデプロイ待たずにフラグ OFF
実装
# フラグ OFF でデプロイ
aws appconfig start-deployment \
--application-id my-app-id \
--environment-id prod-env-id \
--deployment-strategy-id immediate \
--configuration-profile-id feature-flags-id \
--configuration-version 2 # enabled: false
3. A/B テストのフラグ管理
シナリオ
- アルゴリズム A vs B を比較
- ユーザー ID ハッシュで振り分け
実装
import hashlib
def should_use_algorithm_b(user_id: str) -> bool:
"""
ユーザー ID に基づいて Algorithm B を使うか判定
"""
config = get_appconfig('ab-test-algorithm')
if not config.get('enabled'):
return False
# user_id をハッシュして 0-100 の値を算出
hash_value = int(hashlib.md5(user_id.encode()).hexdigest(), 16) % 100
# 50% のユーザーに B を適用
return hash_value < config.get('percentage', 50)
# 使用例
if should_use_algorithm_b(user_id):
result = algorithm_b(data)
else:
result = algorithm_a(data)
4. Lambda の動的設定更新
シナリオ
- Lambda のタイムアウト値・リトライ回数を動的に変更
- 環境変数変更・再デプロイ不要
実装(Python Lambda)
import json
import boto3
appconfig_client = boto3.client('appconfigdata')
def get_config():
"""AppConfig から最新設定を取得"""
try:
response = appconfig_client.start_configuration_session(
ApplicationIdentifier='my-app',
EnvironmentIdentifier='production',
ConfigurationProfileIdentifier='lambda-settings',
RequiredMinimumPollIntervalInSeconds=30
)
token = response['InitialConfigurationToken']
# 設定取得(変更がある場合のみ返す)
config_response = appconfig_client.get_latest_configuration(
ConfigurationToken=token
)
if config_response['Configuration']:
return json.loads(config_response['Configuration'].read())
return {}
except Exception as e:
print(f"Failed to get config: {e}")
return {}
def lambda_handler(event, context):
config = get_config()
timeout_seconds = config.get('timeout_seconds', 30)
max_retries = config.get('max_retries', 3)
log_level = config.get('log_level', 'INFO')
# これらの値を元に処理を実行
result = process_with_timeout(event, timeout_seconds)
return {
'statusCode': 200,
'body': json.dumps(result)
}
5. レート制限値の動的変更
シナリオ
- API のレート制限を 100 RPS から 50 RPS へ動的に低下
- 負荷状況に応じて自動調整
実装
from datetime import datetime, timedelta
import json
class RateLimiter:
def __init__(self):
self.config = self.get_config()
self.requests = []
def get_config(self):
# AppConfig から設定取得
return {
'requests_per_second': 100,
'window_size_seconds': 60
}
def is_allowed(self, user_id: str) -> bool:
"""Rate limit チェック"""
config = self.get_config() # 毎回最新設定を取得
now = datetime.utcnow()
window_start = now - timedelta(seconds=config['window_size_seconds'])
# ウィンドウ外のリクエストを削除
self.requests = [
req_time for req_time in self.requests
if req_time > window_start
]
# リクエスト数チェック
if len(self.requests) < config['requests_per_second']:
self.requests.append(now)
return True
return False
設定・操作の具体例
CLI 例 1:アプリケーション・環境・設定プロファイル作成
# 1. Application 作成
APP_ID=$(aws appconfig create-application \
--name my-app \
--region ap-northeast-1 \
--query 'Application.Id' --output text)
# 2. Environment 作成
ENV_ID=$(aws appconfig create-environment \
--application-id $APP_ID \
--name production \
--region ap-northeast-1 \
--query 'Environment.Id' --output text)
# 3. Configuration Profile(フィーチャーフラグ)作成
CONFIG_PROF_ID=$(aws appconfig create-configuration-profile \
--application-id $APP_ID \
--name feature-flags \
--type FEATURE_FLAGS \
--region ap-northeast-1 \
--query 'ConfigurationProfile.Id' --output text)
echo "App ID: $APP_ID, Env ID: $ENV_ID, Config ID: $CONFIG_PROF_ID"
CLI 例 2:フラグ定義をアップロード
# feature-flags.json を作成
cat > feature-flags.json << 'EOF'
{
"flags": {
"new-checkout": {
"name": "New Checkout Flow"
},
"ai-recommendations": {
"name": "AI Recommendations"
}
},
"values": {
"new-checkout": { "enabled": true },
"ai-recommendations": { "enabled": false }
},
"version": "1"
}
EOF
# Configuration Version をアップロード
VERSION_NUM=$(aws appconfig create-hosted-configuration-version \
--application-id $APP_ID \
--configuration-profile-id $CONFIG_PROF_ID \
--description "Initial feature flags" \
--content fileb://feature-flags.json \
--content-type application/json \
--region ap-northeast-1 \
--query 'VersionNumber' --output text)
echo "Configuration Version: $VERSION_NUM"
CLI 例 3:Canary デプロイ開始
# Canary 戦略 ID 取得(存在しなければ作成)
STRATEGY_ID=$(aws appconfig list-deployment-strategies \
--region ap-northeast-1 \
--query 'Items[?contains(Name, `canary-10`)] | [0].Id' \
--output text)
if [ "$STRATEGY_ID" == "None" ] || [ -z "$STRATEGY_ID" ]; then
STRATEGY_ID=$(aws appconfig create-deployment-strategy \
--name canary-10-percent-5-minutes \
--deployment-duration-in-minutes 5 \
--final-bake-time-in-minutes 10 \
--growth-factor 10.0 \
--growth-type Exponential \
--region ap-northeast-1 \
--query 'Id' --output text)
fi
# デプロイ開始
DEPLOYMENT_ID=$(aws appconfig start-deployment \
--application-id $APP_ID \
--environment-id $ENV_ID \
--deployment-strategy-id $STRATEGY_ID \
--configuration-profile-id $CONFIG_PROF_ID \
--configuration-version $VERSION_NUM \
--description "Release new checkout flow" \
--region ap-northeast-1 \
--query 'DeploymentNumber' --output text)
echo "Deployment started: $DEPLOYMENT_ID"
CLI 例 4:CloudWatch Alarms でロールバック設定
# CloudWatch Alarm 作成(エラー率が 5% を超えた場合)
ALARM_ARN=$(aws cloudwatch put-metric-alarm \
--alarm-name checkout-error-rate-high \
--alarm-description "Alert if checkout error rate > 5%" \
--metric-name ErrorCount \
--namespace MyApp \
--statistic Sum \
--period 60 \
--threshold 5 \
--comparison-operator GreaterThanThreshold \
--region ap-northeast-1 \
--query 'MetricAlarms[0].AlarmArn' --output text)
# Environment にロールバックアラーム設定
aws appconfig update-environment \
--application-id $APP_ID \
--environment-id $ENV_ID \
--monitors "[{
\"AlarmArn\": \"$ALARM_ARN\",
\"AlarmRoleArn\": \"arn:aws:iam::123456789012:role/AppConfigRollbackRole\"
}]" \
--region ap-northeast-1
SDK 例(Python)
import boto3
import json
import time
appconfig = boto3.client('appconfig', region_name='ap-northeast-1')
# 1. アプリケーション作成
app = appconfig.create_application(
Name='my-app',
Description='My Application'
)
app_id = app['Application']['Id']
# 2. 環境作成
env = appconfig.create_environment(
ApplicationId=app_id,
Name='production',
Description='Production environment'
)
env_id = env['Environment']['Id']
# 3. Configuration Profile 作成
config_prof = appconfig.create_configuration_profile(
ApplicationId=app_id,
Name='feature-flags',
Type='FEATURE_FLAGS',
Description='Feature flags configuration'
)
config_prof_id = config_prof['ConfigurationProfile']['Id']
# 4. Configuration Version アップロード
flags_config = {
'flags': {
'new-checkout': {'name': 'New Checkout Flow'},
'ai-recommendations': {'name': 'AI Recommendations'}
},
'values': {
'new-checkout': {'enabled': True},
'ai-recommendations': {'enabled': False}
},
'version': '1'
}
version = appconfig.create_hosted_configuration_version(
ApplicationId=app_id,
ConfigurationProfileId=config_prof_id,
Description='Initial feature flags',
Content=json.dumps(flags_config),
ContentType='application/json'
)
version_num = version['VersionNumber']
# 5. Canary デプロイ開始
strategies = appconfig.list_deployment_strategies()
canary_strategy = [s for s in strategies['Items'] if 'canary' in s['Name']]
strategy_id = canary_strategy[0]['Id'] if canary_strategy else None
if strategy_id:
deployment = appconfig.start_deployment(
ApplicationId=app_id,
EnvironmentId=env_id,
DeploymentStrategyId=strategy_id,
ConfigurationProfileId=config_prof_id,
ConfigurationVersion=str(version_num),
Description='Release new checkout flow'
)
print(f"Deployment started: {deployment['DeploymentNumber']}")
# 6. デプロイ状態確認
time.sleep(5)
deploy_status = appconfig.get_deployment(
ApplicationId=app_id,
EnvironmentId=env_id,
DeploymentNumber=deployment['DeploymentNumber']
)
print(f"Status: {deploy_status['DeploymentStatus']}")
IaC 例(CloudFormation)
AWSTemplateFormatVersion: '2010-09-09'
Description: 'AWS AppConfig Setup'
Resources:
MyApplication:
Type: AWS::AppConfig::Application
Properties:
Name: my-app
Description: My Application
ProductionEnvironment:
Type: AWS::AppConfig::Environment
Properties:
ApplicationId: !Ref MyApplication
Name: production
Description: Production environment
FeatureFlagsProfile:
Type: AWS::AppConfig::ConfigurationProfile
Properties:
ApplicationId: !Ref MyApplication
Name: feature-flags
Type: FEATURE_FLAGS
Description: Feature flags configuration
FeatureFlagsVersion:
Type: AWS::AppConfig::HostedConfigurationVersion
Properties:
ApplicationId: !Ref MyApplication
ConfigurationProfileId: !Ref FeatureFlagsProfile
Description: Initial feature flags
Content: |
{
"flags": {
"new-checkout": {
"name": "New Checkout Flow"
}
},
"values": {
"new-checkout": {
"enabled": true
}
}
}
ContentType: application/json
CanaryDeploymentStrategy:
Type: AWS::AppConfig::DeploymentStrategy
Properties:
Name: canary-10-percent-5-minutes
Description: Canary deployment - 10% for 5 minutes
DeploymentDurationInMinutes: 5
FinalBakeTimeInMinutes: 10
GrowthFactor: 10.0
GrowthType: Exponential
MyDeployment:
Type: AWS::AppConfig::Deployment
Properties:
ApplicationId: !Ref MyApplication
EnvironmentId: !Ref ProductionEnvironment
ConfigurationProfileId: !Ref FeatureFlagsProfile
DeploymentStrategyId: !Ref CanaryDeploymentStrategy
ConfigurationVersion: !Ref FeatureFlagsVersion
Description: Deploy feature flags
IaC 例(Terraform)
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
resource "aws_appconfig_app" "example" {
name = "my-app"
description = "My Application"
}
resource "aws_appconfig_environment" "production" {
application_id = aws_appconfig_app.example.id
name = "production"
description = "Production environment"
state = "Active"
}
resource "aws_appconfig_configuration_profile" "feature_flags" {
application_id = aws_appconfig_app.example.id
name = "feature-flags"
description = "Feature flags configuration"
type = "FEATURE_FLAGS"
validator {
content = jsonencode({
"$schema" = "http://json-schema.org/draft-07/schema#"
type = "object"
})
type = "JSON_SCHEMA"
}
}
resource "aws_appconfig_hosted_configuration_version" "flags" {
application_id = aws_appconfig_app.example.id
configuration_profile_id = aws_appconfig_configuration_profile.feature_flags.configuration_profile_id
description = "Initial feature flags"
content_type = "application/json"
content = jsonencode({
flags = {
"new-checkout" = {
name = "New Checkout Flow"
}
}
values = {
"new-checkout" = {
enabled = true
}
}
})
}
resource "aws_appconfig_deployment_strategy" "canary" {
name = "canary-10-percent-5-minutes"
description = "Canary deployment"
deployment_duration_in_minutes = 5
final_bake_time_in_minutes = 10
growth_factor = 10.0
growth_type = "Exponential"
}
resource "aws_appconfig_deployment" "example" {
application_id = aws_appconfig_app.example.id
environment_id = aws_appconfig_environment.production.environment_id
configuration_profile_id = aws_appconfig_configuration_profile.feature_flags.configuration_profile_id
deployment_strategy_id = aws_appconfig_deployment_strategy.canary.id
configuration_version = aws_appconfig_hosted_configuration_version.flags.version_number
description = "Deploy feature flags"
}
類似サービス比較表
| 観点 | AppConfig | LaunchDarkly | Unleash | CloudWatch Evidently | Split.io |
|---|---|---|---|---|---|
| 管理方式 | AWS ネイティブ | SaaS / エンタープライズ | OSS / SaaS | AWS 統合 | SaaS |
| 段階的ロールアウト | Canary / Linear | Advanced targeting | 機能豊富 | A/B テスト最適化 | 機能豊富 |
| 自動ロールバック | CloudWatch Alarms | 手動 | 手動 | 自動 | 手動 |
| オフライン対応 | AppConfig Agent | SDK キャッシュ | 限定 | なし | 限定 |
| 複数環境対応 | 複数環境 | セグメンテーション | ユーザー戦略 | なし | セグメンテーション |
| 学習曲線 | 低(AWS の知識で十分) | 中 | 中 | 低 | 中 |
| 料金 | 低(API 呼び出し単位) | $75/月~ | OSS は無料 | 従量課金 | $500/月~ |
| 推奨用途 | AWS 環境・シンプルなフラグ | エンタープライズ・複雑ターゲティング | OSS 環境・完全管理 | A/B テスト・実験 | モバイルアプリ・複雑ターゲティング |
ベストプラクティス
チェックリスト(優先順)
✅ 推奨事項
- [ ] フラグ名を明確に定義 → kebab-case で統一、ドキュメント記載
- [ ] Canary / Linear 戦略で段階的展開 → 本番環境では Immediate 避ける
- [ ] CloudWatch Alarms で自動ロールバック設定 → エラー率・レイテンシ監視
- [ ] JSON Schema バリデーター設定 → 設定ミス事前防止
- [ ] AppConfig Agent でキャッシング → 高頻度呼び出しのコスト最適化
- [ ] フラグ ON/OFF の監査ログ → CloudTrail で追跡
- [ ] 複数環境で同じフラグ定義 → 本番・ステージング・開発を統一
- [ ] フラグの定期的なクリーンアップ → 使われなくなったフラグを削除
- [ ] 段階的リリース前のテスト → ステージングで Canary デプロイをシミュレート
- [ ] ドキュメント化 → フラグの目的・有効期限・削除予定日を記載
❌ アンチパターン
| アンチパターン | 問題 | 代替 |
|---|---|---|
| 本番環境で Immediate デプロイ | ダウンタイムリスク、問題検知が遅い | Canary / Linear 使用 |
| CloudWatch Alarms なしでデプロイ | 異常検知に数分かかり、影響範囲拡大 | アラーム設定で自動ロールバック |
| フラグ定義の属性を変更し続ける | スキーマの型一貫性失失失 | 新しい属性フラグを作成 |
| AppConfig Agent キャッシング未使用 | API 呼び出し多発、コスト増加 | Lambda Extension / EC2 Agent 使用 |
| ドキュメントなしでフラグ展開 | フラグの目的・有効期限不明確 | フラグごとにドキュメント作成 |
| 複数チームで別フラグ定義 | 同じ機能なのに異なるフラグ名 | 統一フラグ定義・命名規約 |
トラブルシューティング
| 症状 | 原因 | 解決策 |
|---|---|---|
| 「設定が反映されない」 | AppConfig Agent キャッシュが古い、ポーリング間隔が長い | Agent 再起動、ポーリング間隔短縮 |
| 「バリデーションエラー」 | JSON スキーマが厳しすぎ、Lambda Validator エラー | スキーマ条件・Lambda ロジック見直し |
| 「デプロイが中断」 | Validation 失敗、Rollback トリガー(Alarm 発火) | ログ確認、設定値修正、アラーム再設定 |
| 「高いコスト」 | API 呼び出し過多、AppConfig Agent 未使用 | Agent キャッシング導入、ポーリング間隔調整 |
| 「フラグ ON/OFF が切り替わらない」 | Application / Environment / Profile ID 誤り、バージョン不正 | ID・バージョン番号確認 |
| 「AppConfig Agent が起動しない」 | IAM 権限不足、ネットワーク不通 | IAM ロール権限確認、VPC 設定確認 |
| 「複数バージョン間での競合」 | 同時デプロイで古いバージョンが優先 | デプロイ順序調整、ロック機構導入 |
2025-2026 最新動向
2026年3月:Enhanced Targeting リリース
新機能
- ユーザーセグメンテーション(属性ベース)
- 複数条件での AND / OR ロジック
- デプロイ対象ユーザーの動的フィルタリング
{
"flags": {
"premium-feature": {
"name": "Premium Feature",
"targeting": {
"rules": [
{
"condition": "user_tier == 'premium'",
"enabled": true
},
{
"condition": "region in ['jp', 'sg']",
"enabled": false
}
]
}
}
}
}
2025年4月:CloudWatch Evidence 統合
新機能
- デプロイ結果の自動分析
- A/B テスト結果の推奨値提示
- 統計的有意性の自動判定
2025年5月:AppConfig Agent Lambda Extension 拡張
改善点
- オフライン対応强化
- より効率的なキャッシング戦略
- ローカル開発モードの充実
Lambda Layer ARN(2025年最新)
- arn:aws:lambda:ap-northeast-1:027255383542:layer:AWS-AppConfig-Extension:latest
学習リソース・参考文献
公式ドキュメント
-
AWS AppConfig User Guide
-
AWS AppConfig API Reference
-
AWS AppConfig Pricing
-
CloudWatch Evidence Documentation
AWS ブログ・サンプルコード
-
AWS Systems Manager Blog - AppConfig Articles
- フィーチャーフラグ・ベストプラクティス記事
-
AWS Samples - AppConfig Examples
- GitHub のサンプルコード集
関連プロダクト
-
AWS Amplify Feature Flags(AppConfig 統合)
-
AWS Systems Manager Parameter Store(設定管理)
OSS / サードパーティリソース
-
LaunchDarkly Documentation
-
Unleash - Open Source Feature Toggle Service
実装例
例 1:Python アプリケーションでのフラグ利用
import json
import boto3
from functools import lru_cache
from datetime import datetime, timedelta
class AppConfigClient:
def __init__(self, app_name: str, env_name: str, config_name: str):
self.appconfig = boto3.client('appconfigdata', region_name='ap-northeast-1')
self.app_name = app_name
self.env_name = env_name
self.config_name = config_name
self.token = None
self.cache_time = None
self.cache_ttl = timedelta(minutes=5)
def get_config(self) -> dict:
"""Configuration を取得(キャッシュ活用)"""
now = datetime.utcnow()
# キャッシュ有効期限チェック
if self.cache_time and (now - self.cache_time) < self.cache_ttl:
return self.cached_config
try:
# 初回または キャッシュ期限切れ時に取得
if not self.token:
session = self.appconfig.start_configuration_session(
ApplicationIdentifier=self.app_name,
EnvironmentIdentifier=self.env_name,
ConfigurationProfileIdentifier=self.config_name,
RequiredMinimumPollIntervalInSeconds=60
)
self.token = session['InitialConfigurationToken']
response = self.appconfig.get_latest_configuration(
ConfigurationToken=self.token
)
self.token = response['NextConfigurationToken']
if response['Configuration']:
config_data = json.loads(response['Configuration'].read())
self.cached_config = config_data
self.cache_time = now
return config_data
return self.cached_config if hasattr(self, 'cached_config') else {}
except Exception as e:
print(f"Error fetching config: {e}")
return self.cached_config if hasattr(self, 'cached_config') else {}
def is_flag_enabled(self, flag_name: str) -> bool:
"""フラグが有効か判定"""
config = self.get_config()
flags = config.get('values', {})
flag = flags.get(flag_name, {})
return flag.get('enabled', False)
def get_flag_value(self, flag_name: str, key: str, default=None):
"""フラグの属性値を取得"""
config = self.get_config()
flags = config.get('values', {})
flag = flags.get(flag_name, {})
return flag.get(key, default)
# 使用例
def checkout_flow(user_id: str):
config = AppConfigClient('my-app', 'production', 'feature-flags')
if config.is_flag_enabled('new-checkout-flow'):
return new_checkout_ui()
else:
return legacy_checkout_ui()
def ai_recommendations(user_id: str):
config = AppConfigClient('my-app', 'production', 'feature-flags')
if config.is_flag_enabled('ai-recommendations'):
model_version = config.get_flag_value('ai-recommendations', 'model-version', 'v1')
max_recs = config.get_flag_value('ai-recommendations', 'max-recommendations', 5)
return get_ai_recommendations(user_id, model_version, max_recs)
else:
return get_legacy_recommendations(user_id)
例 2:Node.js / Lambda での動的レート制限
const AWS = require('aws-sdk');
const appconfig = new AWS.AppConfigData({ region: 'ap-northeast-1' });
let configCache = null;
let cacheExpireTime = 0;
async function getConfig() {
const now = Date.now();
// キャッシュ有効チェック(5分間有効)
if (configCache && cacheExpireTime > now) {
return configCache;
}
try {
const sessionResponse = await appconfig.startConfigurationSession({
ApplicationIdentifier: 'my-app',
EnvironmentIdentifier: 'production',
ConfigurationProfileIdentifier: 'rate-limits',
RequiredMinimumPollIntervalInSeconds: 60
}).promise();
const token = sessionResponse.InitialConfigurationToken;
const configResponse = await appconfig.getLatestConfiguration({
ConfigurationToken: token
}).promise();
if (configResponse.Configuration) {
configCache = JSON.parse(configResponse.Configuration);
cacheExpireTime = now + (5 * 60 * 1000); // 5分
return configCache;
}
return configCache || {};
} catch (error) {
console.error('Failed to get config:', error);
return configCache || {};
}
}
class RateLimiter {
constructor() {
this.requests = new Map();
}
async isAllowed(userId) {
const config = await getConfig();
const rateLimitPerSecond = config.rate_limit_per_second || 100;
const now = Date.now();
const windowStart = now - 60000; // 60秒ウィンドウ
if (!this.requests.has(userId)) {
this.requests.set(userId, []);
}
const userRequests = this.requests.get(userId);
// ウィンドウ外リクエストを削除
const validRequests = userRequests.filter(time => time > windowStart);
if (validRequests.length < rateLimitPerSecond) {
validRequests.push(now);
this.requests.set(userId, validRequests);
return true;
}
return false;
}
}
const limiter = new RateLimiter();
exports.handler = async (event) => {
const userId = event.requestContext.authorizer.principalId;
if (!await limiter.isAllowed(userId)) {
return {
statusCode: 429,
body: JSON.stringify({ error: 'Rate limit exceeded' })
};
}
return {
statusCode: 200,
body: JSON.stringify({ message: 'Request processed' })
};
};
チェックリスト
デプロイ前
- [ ] フラグ定義を JSON で作成・検証
- [ ] JSON Schema / Lambda バリデーター設定
- [ ] ステージング環境で Canary デプロイ テスト
- [ ] CloudWatch Alarms(エラー率・レイテンシ)設定
- [ ] Rollback IAM ロール作成・権限確認
- [ ] AppConfig Agent インストール・IAM ロール設定
デプロイ後
- [ ] デプロイステータス確認(Pending → In Progress → Complete)
- [ ] CloudWatch Logs で Validator エラー確認
- [ ] メトリクス・ログを監視(自動ロールバック検知)
- [ ] アプリケーションで フラグ有効確認
- [ ] 段階的展開が期待通りに進行确认
運用時
- [ ] 月 1 回以上 フラグ定義レビュー
- [ ] 不要フラグの削除(クリーンアップ)
- [ ] CloudTrail でフラグ ON/OFF 操作監査
- [ ] AppConfig Agent ログ・メトリクス監視
- [ ] フラグ有効期限の事前通知・削除計画
まとめ
AWS AppConfig は 「フィーチャーフラグ・動的設定を安全にデプロイするサービスで、Canary・Linear 段階的ロールアウト・JSON Schema / Lambda バリデーション・CloudWatch Alarms 自動ロールバックを実現するサービス」 です。
AppConfig が向いている場合
- 新機能を段階的にリリースしたい
- 本番環境でコードデプロイなしに設定値を変更したい
- AWS 環境での シンプルなフィーチャーフラグ管理
- CloudWatch と統合した自動ロールバック機能が必要
2025-2026 動向
- Enhanced Targeting: ユーザーセグメンテーション・属性ベースフラグ
- CloudWatch Evidence 統合: A/B テスト自動分析
- AppConfig Agent 拡張: オフライン対応・キャッシング効率化
フラグ名を明確に定義し、Canary / Linear 戦略で段階的に展開、CloudWatch Alarms で自動ロールバック設定、定期的にフラグをクリーンアップすることで、高速で安全な本番環境での動作制御を実現してください。
最終更新:2026-04-27 バージョン:v2.0