「desiredCountを手で変えるのは限界がある。でもオートスケールの設定を雑にすると、逆にフラッピングして不安定になる」——ECS on Fargateを本番に持ち込むとき、必ずこの局面が来ます。
私は決済基盤(本番二重課金0件)でSQS駆動の冪等ワーカーをFargate上で運用し、木材流通B2B SaaSではAPI Gateway → NLB → ALB → ECS on Fargateの上に221本のAPIエンドポイントを本番稼働させてきました。どちらも「速く増やし、慎重に減らす」という非対称スケーリングの考え方と、ワークロードに合ったメトリクス選択が安定の核心でした。
本稿はECS on Fargate 本番運用ガイドの続編として、オートスケーリング設計に特化します。HTTPサービスとSQSワーカーという2つの代表的なワークロードで、それぞれ最適な設計を実コード付きで体系化します。
なぜ手動 desiredCount では限界があるか
手動でdesired_countを調整する運用には3つの根本的な限界があります。
- 反応が遅い:人間がアラートに気づき、Terraformを適用するまでにスパイクは終わっているか、すでにSLAを割っているかのどちらかです。
- 縮小を忘れる:増やしたタスクを減らし損ねると、コストが静かに膨らみ続けます。
- SQS長が読めない:キューにメッセージが溜まっていても、CPUは動いていないため気づけません。
Application Auto Scalingは「計測値が閾値を超えたらdesiredCountを動かす」という仕組みをポリシーとして宣言し、ECSサービスコントローラに委譲します。あなたがやることは目標値と上下限を決めるだけです。
仕組み:Application Auto Scaling が ECS の desiredCount を動かす
ECSのオートスケーリングは、AWS Application Auto Scalingというサービスが担います。これは単独のサービスで、ECS以外にDynamoDB・Aurora・Lambda・SageMakerなども同じAPIで扱います。ECS固有の話は3つの要素に整理されます。
スケーラブルターゲット
まず「何をスケールするか」を登録します。これがスケーラブルターゲットです。
resource "aws_appautoscaling_target" "app" {
service_namespace = "ecs" # ECS専用の名前空間
scalable_dimension = "ecs:service:DesiredCount" # 操作するのはdesiredCount
resource_id = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.app.name}"
min_capacity = 2 # 最低タスク数(下限。0にするとアイドルゼロが可能)
max_capacity = 20 # 最大タスク数(上限)
}
resource_idの形式はservice/<cluster_name>/<service_name>です。スペルミスしてもTerraformのapplyは通ってしまいますが、スケーリングが一切機能しなくなります。applyした後はaws application-autoscaling describe-scalable-targetsで実際に登録されたか確認するのを習慣にしましょう。
スケーリングポリシー
次に「いつ・どう動かすか」をポリシーで定義します。大きく3種類あります。
| ポリシー種別 | 判断基準 | 主な用途 |
|---|---|---|
| ターゲット追跡 | 目標メトリクス値を維持 | 定常サービス(CPU・リクエスト数) |
| ステップスケーリング | CloudWatchアラームの段階で増減幅を変える | バースト対応・非線形負荷 |
| スケジュールスケーリング | 時刻ベースでmin/max/desiredを変更 | 既知のピーク(業務時間・キャンペーン) |
クールダウン
スケーリングアクション後に次のアクションを抑制する待機時間です。スケールアウトは短く、スケールインは長く——これが唯一の定石です。スパイク直後に縮めて再び慌てる「フラッピング」を防ぐためです。
ターゲット追跡(Target Tracking):目標値を宣言して任せる
最もシンプルで、ほとんどのHTTPサービスはこれで十分です。
事前定義メトリクス
ECSサービスに対して使える事前定義メトリクスは3つです(公式)。
| predefined_metric_type | 計測対象 | いつ使うか |
|---|---|---|
ECSServiceAverageCPUUtilization | サービス内タスクのCPU平均使用率(%) | CPUバウンドな処理(演算・エンコード) |
ECSServiceAverageMemoryUtilization | サービス内タスクのメモリ平均使用率(%) | メモリバウンドな処理(大量データ展開) |
ALBRequestCountPerTarget | ALBターゲット1台あたりのリクエスト数 | HTTPトラフィックに線形追従したい |
選び方の原則:ボトルネックになっているリソースを使う。分からなければContainer Insightsで実測してから決める。CPU/メモリとリクエスト数を両方設定するとより安全(どちらかがトリガーになった時点でスケールアウトされる)。
完全な Terraform 例(CPU + ALBRequestCountPerTarget)
# --- スケーラブルターゲット(1回定義すれば複数ポリシーを紐付けられる) ---
resource "aws_appautoscaling_target" "app" {
service_namespace = "ecs"
scalable_dimension = "ecs:service:DesiredCount"
resource_id = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.app.name}"
min_capacity = 2
max_capacity = 20
depends_on = [aws_ecs_service.app] # サービスが先に存在していること
}
# --- CPU ターゲット追跡 ---
resource "aws_appautoscaling_policy" "cpu_tt" {
name = "cpu-target-tracking"
policy_type = "TargetTrackingScaling"
service_namespace = aws_appautoscaling_target.app.service_namespace
resource_id = aws_appautoscaling_target.app.resource_id
scalable_dimension = aws_appautoscaling_target.app.scalable_dimension
target_tracking_scaling_policy_configuration {
predefined_metric_specification {
predefined_metric_type = "ECSServiceAverageCPUUtilization"
}
target_value = 60.0 # 60%を維持。70〜80%は高すぎてバースト余裕がなくなる
scale_out_cooldown = 30 # スケールアウトは速く(秒)
scale_in_cooldown = 300 # スケールインは慎重に(秒)
disable_scale_in = false # スケールインも自動で行う(コスト管理)
}
}
# --- ALBリクエスト数 ターゲット追跡 ---
resource "aws_appautoscaling_policy" "alb_tt" {
name = "alb-request-count-target-tracking"
policy_type = "TargetTrackingScaling"
service_namespace = aws_appautoscaling_target.app.service_namespace
resource_id = aws_appautoscaling_target.app.resource_id
scalable_dimension = aws_appautoscaling_target.app.scalable_dimension
target_tracking_scaling_policy_configuration {
predefined_metric_specification {
predefined_metric_type = "ALBRequestCountPerTarget"
# ALBとターゲットグループのリソースラベルが必要
resource_label = "${aws_lb.main.arn_suffix}/${aws_lb_target_group.app.arn_suffix}"
}
target_value = 1000 # タスク1台あたり1000 req/min を目標
scale_out_cooldown = 30
scale_in_cooldown = 300
}
}
resource_labelはALBRequestCountPerTargetだけで必要な指定です。フォーマットは<load-balancer-arn-suffix>/<target-group-arn-suffix>で、aws_lb・aws_lb_target_groupリソースのarn_suffix属性で取れます。
target_value の選び方
- CPU:60〜70%が一般的。80%以上に設定するとバーストの余白がなく、スケールアウトが間に合わない。
- ALBリクエスト数:ローカルまたはステージング環境でタスク1台あたりの処理可能リクエスト数を計測し、その6〜7割を目標にする。憶測で設定せず計測ファースト。
ステップスケーリング:段階的に増減幅を変える
バーストが激しいワークロードや「ちょっとした超過は小幅に、大幅な超過は一気に増やしたい」という非線形な需要にはステップスケーリングが適合します。
ターゲット追跡との使い分け
| 観点 | ターゲット追跡 | ステップスケーリング |
|---|---|---|
| 設定の複雑さ | 低い(目標値だけ) | 高い(アラーム + ステップ定義) |
| スケール量の制御 | AWS自動計算 | 自分で段階を定義 |
| 向いているケース | 定常的なHTTPサービス | バースト・非線形・精密な制御が必要な場合 |
| 組み合わせ | 単独でOK | ターゲット追跡と共存も可能 |
ステップスケーリングはCloudWatchアラームと連動します。アラームが「ALARM状態」になるとスケールアウト、「OK状態に戻る」ときにスケールインのポリシーを定義します。
# CloudWatchアラーム(スケールアウトトリガー)
resource "aws_cloudwatch_metric_alarm" "cpu_high" {
alarm_name = "ecs-cpu-high"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 2
metric_name = "CPUUtilization"
namespace = "AWS/ECS"
period = 60
statistic = "Average"
threshold = 70.0
dimensions = {
ClusterName = aws_ecs_cluster.main.name
ServiceName = aws_ecs_service.app.name
}
alarm_actions = [aws_appautoscaling_policy.step_out.arn]
}
# ステップスケールアウトポリシー
resource "aws_appautoscaling_policy" "step_out" {
name = "step-scale-out"
policy_type = "StepScaling"
service_namespace = aws_appautoscaling_target.app.service_namespace
resource_id = aws_appautoscaling_target.app.resource_id
scalable_dimension = aws_appautoscaling_target.app.scalable_dimension
step_scaling_policy_configuration {
adjustment_type = "ChangeInCapacity" # 絶対値で変える(他にPercentChangeInCapacityも可)
cooldown = 60
metric_aggregation_type = "Average"
step_adjustment {
# CPU 70〜80%: +2タスク
metric_interval_lower_bound = 0
metric_interval_upper_bound = 10
scaling_adjustment = 2
}
step_adjustment {
# CPU 80%超: +5タスク(バースト対応)
metric_interval_lower_bound = 10
scaling_adjustment = 5
}
}
}
metric_interval_lower_boundとupper_boundは、アラームの閾値からの差分(ブリーチ量)で指定します。「閾値70%に対してCPUが73%」なら差分は+3——0〜10のステップに入ります。
スケジュールスケーリング:ピークを先読みする
毎朝9時の業務開始、月次のキャンペーン、バッチ前のウォームアップなど、いつ負荷が来るかわかっている場合はスケジュールスケーリングで先回りします。
# 平日9時にスケールアウト(JST = UTC+9、なのでUTCは0時)
resource "aws_appautoscaling_scheduled_action" "scale_up_business_hours" {
name = "scale-up-business-hours"
service_namespace = aws_appautoscaling_target.app.service_namespace
resource_id = aws_appautoscaling_target.app.resource_id
scalable_dimension = aws_appautoscaling_target.app.scalable_dimension
schedule = "cron(0 0 ? * MON-FRI *)" # UTC 0:00 = JST 9:00
scalable_target_action {
min_capacity = 5 # ピーク時の下限を引き上げる
max_capacity = 30 # ピーク時の上限を広げる
}
}
# 平日21時に縮小(JST = UTC 12:00)
resource "aws_appautoscaling_scheduled_action" "scale_down_off_hours" {
name = "scale-down-off-hours"
service_namespace = aws_appautoscaling_target.app.service_namespace
resource_id = aws_appautoscaling_target.app.resource_id
scalable_dimension = aws_appautoscaling_target.app.scalable_dimension
schedule = "cron(0 12 ? * MON-FRI *)" # UTC 12:00 = JST 21:00
scalable_target_action {
min_capacity = 2 # 夜間の下限に戻す
max_capacity = 20 # 夜間の上限に戻す
}
}
スケジュールスケーリングとターゲット追跡は共存できます。ピーク時間帯にはmin_capacityを引き上げてウォームな状態を保ち、ターゲット追跡がさらに細かく増減を調整するという組み合わせが本番でよく機能します。
SQS 駆動ワーカーのスケーリング:「バックログ・パー・タスク」パターン
ここからが本稿の核心です。HTTPサービスとは全く異なる設計が必要です。
なぜ CPU ではダメか
SQSワーカーは「キューにメッセージがあれば処理し、なければ待つ」という構造です。キューが空でもワーカーは起動したまま待機しているため、CPU使用率はほぼゼロになります。逆に、大量のメッセージが積まれていてもワーカーがIO待ち主体の処理(外部API呼び出し・DB書き込みなど)をしていれば、CPU使用率は低いままです。
つまりCPUと処理待ちメッセージ数の間に相関がないのです。CPU追跡でSQSワーカーをスケールするのは、ガソリン残量ではなくエンジン回転数で燃料補給タイミングを決めるようなものです。
AWS 推奨:バックログ・パー・タスク
AWSが公式に推奨するパターンは、**「バックログ・パー・タスク(Backlog Per Task)」**です(Scaling based on Amazon SQS、コンセプトはEC2 Auto ScalingのドキュメントですがECS Application Auto Scalingでも同じ原則が適用されます)。
計算式はシンプルです。
バックログ・パー・タスク = ApproximateNumberOfMessagesVisible ÷ RunningTaskCount
これを**目標バックログ(Target Backlog)**に向けてターゲット追跡します。目標バックログの設定値は、許容レイテンシから逆算します。
目標バックログの算出(例)
以下は架空の例として、計算方法を示します。実際の値はワークロードの計測から求めてください。
例(illustrative values — 実計測値ではありません):
- 1メッセージあたりの平均処理時間:5秒
- タスク1台あたりの同時処理数(concurrency):1(シングルスレッドワーカー)
- タスク1台が1分間に処理できるメッセージ数:60秒 ÷ 5秒 = 12件/分
- 許容メッセージ滞留時間(最大レイテンシ目標):1分
→ 目標バックログ = 許容レイテンシ(秒) ÷ 1メッセージ処理秒
= 60秒 ÷ 5秒
= 12
つまり「タスク1台あたり最大12件のバックログを目標に追跡する」と設定する。
バックログが36件あればタスクを3台に、120件なら10台に増やす、という挙動になる。
0除算問題の扱い
RunningTaskCountが0のとき(アイドルでmin_capacity=0に縮んでいる状態)に除算するとゼロ除算になります。この場合、メッセージ数そのものを目標値として使うか、RunningTaskCountを最低1として扱うかのどちらかで対処します。カスタムメトリクスの発行ロジックで吸収するのが最も安全です。
カスタムメトリクスの発行
SQS関連のメトリクス(ApproximateNumberOfMessagesVisible)はCloudWatchに自動で届きますが、RunningTaskCountとの比率(バックログ・パー・タスク)は自分で計算してCloudWatchカスタムメトリクスとして発行する必要があります。
TypeScript(EventBridge Schedulerで定期実行するLambda)の例:
import {
CloudWatchClient,
PutMetricDataCommand,
} from "@aws-sdk/client-cloudwatch";
import {
SQSClient,
GetQueueAttributesCommand,
} from "@aws-sdk/client-sqs";
import {
ECSClient,
DescribeServicesCommand,
} from "@aws-sdk/client-ecs";
const cw = new CloudWatchClient({});
const sqs = new SQSClient({});
const ecs = new ECSClient({});
const QUEUE_URL = process.env.QUEUE_URL!;
const CLUSTER = process.env.ECS_CLUSTER!;
const SERVICE = process.env.ECS_SERVICE!;
const NAMESPACE = "Custom/ECS";
const METRIC_NAME = "BacklogPerTask";
export async function handler(): Promise<void> {
// 1) SQS の可視メッセージ数を取得
const sqsRes = await sqs.send(
new GetQueueAttributesCommand({
QueueUrl: QUEUE_URL,
AttributeNames: ["ApproximateNumberOfMessages"],
}),
);
const visibleMessages = parseInt(
sqsRes.Attributes?.ApproximateNumberOfMessages ?? "0",
10,
);
// 2) ECS の Running タスク数を取得
const ecsRes = await ecs.send(
new DescribeServicesCommand({ cluster: CLUSTER, services: [SERVICE] }),
);
const runningCount = ecsRes.services?.[0]?.runningCount ?? 0;
// 3) バックログ・パー・タスクを計算(0除算を安全に処理)
// runningCount=0 のときはメッセージ数をそのまま発行し、
// スケールアウトが起動するようにする
const backlogPerTask =
runningCount > 0 ? visibleMessages / runningCount : visibleMessages;
console.log({ visibleMessages, runningCount, backlogPerTask });
// 4) CloudWatch カスタムメトリクスへ発行
await cw.send(
new PutMetricDataCommand({
Namespace: NAMESPACE,
MetricData: [
{
MetricName: METRIC_NAME,
Value: backlogPerTask,
Unit: "Count",
Dimensions: [
{ Name: "ClusterName", Value: CLUSTER },
{ Name: "ServiceName", Value: SERVICE },
],
},
],
}),
);
}
このLambdaをEventBridge Scheduler で1分ごとに実行します。CloudWatchのカスタムメトリクスの解像度は最小1分なので、これで十分です。
Bash(シェルスクリプトで手動確認・デバッグ用):
#!/usr/bin/env bash
set -euo pipefail
QUEUE_URL="${QUEUE_URL:?QUEUE_URL not set}"
CLUSTER="${ECS_CLUSTER:?ECS_CLUSTER not set}"
SERVICE="${ECS_SERVICE:?ECS_SERVICE not set}"
REGION="${AWS_REGION:-ap-northeast-1}"
# SQS 可視メッセージ数
VISIBLE=$(aws sqs get-queue-attributes \
--queue-url "$QUEUE_URL" \
--attribute-names ApproximateNumberOfMessages \
--query 'Attributes.ApproximateNumberOfMessages' \
--output text \
--region "$REGION")
# ECS Running タスク数
RUNNING=$(aws ecs describe-services \
--cluster "$CLUSTER" \
--services "$SERVICE" \
--query 'services[0].runningCount' \
--output text \
--region "$REGION")
if [[ "$RUNNING" -gt 0 ]]; then
BACKLOG=$(echo "scale=2; $VISIBLE / $RUNNING" | bc)
else
BACKLOG="$VISIBLE"
fi
echo "visible=$VISIBLE running=$RUNNING backlog_per_task=$BACKLOG"
# CloudWatch に発行
aws cloudwatch put-metric-data \
--namespace "Custom/ECS" \
--metric-name "BacklogPerTask" \
--value "$BACKLOG" \
--unit "Count" \
--dimensions "Name=ClusterName,Value=$CLUSTER" "Name=ServiceName,Value=$SERVICE" \
--region "$REGION"
Terraform:カスタムメトリクスを使ったターゲット追跡
resource "aws_appautoscaling_target" "worker" {
service_namespace = "ecs"
scalable_dimension = "ecs:service:DesiredCount"
resource_id = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.worker.name}"
min_capacity = 0 # アイドル時はゼロに縮む(コスト最適化)
max_capacity = 50 # 上限は処理能力と許容コストから設定
}
resource "aws_appautoscaling_policy" "worker_backlog" {
name = "sqs-backlog-per-task"
policy_type = "TargetTrackingScaling"
service_namespace = aws_appautoscaling_target.worker.service_namespace
resource_id = aws_appautoscaling_target.worker.resource_id
scalable_dimension = aws_appautoscaling_target.worker.scalable_dimension
target_tracking_scaling_policy_configuration {
customized_metric_specification {
metric_name = "BacklogPerTask"
namespace = "Custom/ECS"
statistic = "Average"
dimensions {
name = "ClusterName"
value = aws_ecs_cluster.main.name
}
dimensions {
name = "ServiceName"
value = aws_ecs_service.worker.name
}
}
target_value = 12 # 上の計算例で求めた目標バックログ
scale_out_cooldown = 60 # キュー急増への応答を速く
scale_in_cooldown = 300 # 処理しきるまでの余裕を持って縮小
disable_scale_in = false
}
}
min_capacity=0 の起動遅延
min_capacity=0(アイドルゼロ)にすると、タスクがゼロの状態からスケールアウトするとき、Fargateのタスク起動時間(ENI割り当て・イメージpull・アプリ起動込みで概ね数十秒)が加わります。この「コールドスタート」期間はメッセージが処理されないので、許容レイテンシに対して起動時間が無視できない場合はmin_capacity=1以上にすることを検討してください。決済基盤のワーカーでは厳しいレイテンシSLAがあったためmin_capacity=1を維持しました。
アンチパターンとトラブルシューティング
フラッピング(増減の繰り返し)
症状:スケールアウト直後にスケールインし、またスケールアウトするサイクルが止まらない。
原因:scale_in_cooldownが短すぎる。スケールアウト後の負荷が落ち着く前にスケールインが走り、また負荷が上がる。
対処:scale_in_cooldownをscale_out_cooldownの数倍(最低300秒)に設定する。disable_scale_in = trueを一時的に使うのもフラッピング診断には有効ですが、コスト管理ができなくなるため本番では使わない。
ヘルスチェック猶予を忘れる
スケールアウトで新しいタスクが起動し、ALBに登録されてもアプリの初期化が終わっていない間はヘルスチェックが失敗します。health_check_grace_period_secondsを設定しないと、起動中のタスクが即座に不健全扱いで落とされ、スケールアウトがデスマーチになります。
resource "aws_ecs_service" "app" {
# ...
health_check_grace_period_seconds = 30 # アプリ起動時間に応じて調整
}
また、タスク定義のhealthCheck.startPeriodも忘れずに設定します(ピラー記事の実装①参照)。
スケールインで処理中タスクを殺さない
スケールインが発生すると、ECSはタスクにSIGTERMを送ります。SQSワーカーがメッセージを処理中にSIGTERMを受け、stopTimeout(既定30秒・最大120秒)を過ぎてSIGKILLで殺されると、処理中のメッセージが中断されてvisibility timeoutまでリトライ不能になります。
正しい対処は3点セットです。
- SIGTERMハンドラを実装する(新規メッセージの受信を止め、処理中のメッセージを捌き切る)。
stopTimeoutを処理完了に十分な時間に設定する(最大120秒。5秒かかるメッセージを1件処理している最中にSIGTERMが来る最悪ケースを想定して設定)。- 冪等性を担保する(万が一SIGKILL後に再配信されても二重処理しない)。
// SQS ワーカーの SIGTERM ハンドリング(概念例)
let isShuttingDown = false;
process.on("SIGTERM", () => {
console.log("SIGTERM received: stopping new message consumption");
isShuttingDown = true;
// 処理中のメッセージが完了するのを待ち、stopTimeout内にexitする
});
async function pollMessages(): Promise<void> {
while (!isShuttingDown) {
const messages = await receiveMessages();
for (const msg of messages) {
await processMessage(msg); // 冪等な処理
await deleteMessage(msg); // 正常終了後にのみ削除
}
}
console.log("Worker gracefully stopped");
process.exit(0);
}
冪等な非同期処理の詳細な実装パターンはSQS・Lambda・EventBridgeの冪等非同期処理ガイドを、回路遮断・リトライの設計はリトライ・バックオフ・サーキットブレーカーを参照してください。
スケーリング設定が効いているか確認する
# スケーラブルターゲットの確認
aws application-autoscaling describe-scalable-targets \
--service-namespace ecs \
--query 'ScalableTargets[*].{Resource:ResourceId,Min:MinCapacity,Max:MaxCapacity}'
# スケーリングアクティビティ(直近のスケール履歴)
aws application-autoscaling describe-scaling-activities \
--service-namespace ecs \
--resource-id "service/<cluster>/<service>" \
--max-results 10
スケーリング履歴を定期的に確認し、フラッピングや想定外のスケールイン・アウトが起きていないかをモニタリングに組み込みます。OpenTelemetry × ECS の可観測性と合わせてダッシュボードに載せておくと、スケーリング挙動の異常に素早く気づけます。
本番リリース前チェックリスト
- スケーラブルターゲットが
describe-scalable-targetsで正しく登録されているか確認した -
min_capacityとmax_capacityはビジネス要件(コスト上限・SLA)から決めたか -
scale_out_cooldown < scale_in_cooldown(非対称)になっているか - CPUターゲット追跡の
target_valueは計測ベースか(60〜70%が目安) -
ALBRequestCountPerTargetを使う場合、resource_labelが正しく設定されているか - SQSワーカーはCPU追跡ではなくバックログ・パー・タスクを使っているか
- カスタムメトリクス発行Lambdaは1分ごとに実行され、CloudWatch上でデータポイントが確認できるか
-
min_capacity=0の場合、コールドスタート遅延を許容レイテンシと照合したか -
health_check_grace_period_secondsを設定し、起動時の誤検知による強制終了を防いでいるか - SIGTERMハンドラを実装し、
stopTimeout内に処理を完了できるか検証したか - スケールイン後もメッセージの二重処理が起きないよう冪等性を担保しているか
- スケーリングアクティビティのログを可観測性ダッシュボードに組み込んだか
- コスト最適化視点でFargate Spotとの組み合わせをコスト最適化ガイドで確認したか
まとめ
ECS on Fargateのオートスケーリングは、「メトリクスを正しく選ぶ」「非対称クールダウンでフラッピングを防ぐ」「グレースフルシャットダウンと連動させる」の3点が本番品質の土台です。
- HTTPサービス:ターゲット追跡(CPU + ALBRequestCountPerTarget)で十分。バーストがある場合はステップスケーリングを追加する。
- SQSワーカー:CPUは使わない。バックログ・パー・タスクをカスタムメトリクスで発行し、許容レイテンシから逆算した目標値でターゲット追跡する。
- 共通:SIGTERMハンドリング・
stopTimeout・冪等性の三点セットなしにスケールインは安全に運用できない。
私が一人 × 生成AIで決済基盤とB2B SaaSを本番運用してきた経験から言えるのは、「ツールを正しく使えば、少人数でも世界水準のインフラは手の届く場所にある」ということです。オートスケーリングの設計・見直し・トラブルシューティングについてご相談があれば、お気軽にどうぞ。