Based on the MLA-C01 exam guideReport an error
update_endpoint → SageMaker swaps it in with Blue/Green.SageMakerVariantInvocationsPerInstance is the standard. With a minimum of 1 instance, it cannot scale down to 0.MinCapacity.Almost every online service where users wait for results is deployed as a real-time endpoint. This endpoint is made of the following three resources.
model.tar.gz) with the container image that holds the inference code.S3 model.tar.gz ─┐
├─▶ [ Model ] ─▶ [ EndpointConfig ] ─▶ [ Endpoint ]
Container image ─┘ artifact+code instance type/count HTTPS address
ProductionVariant (what the caller sees)
Key point: the three are separate resources. If you leave the Endpoint address
as it is and swap only the EndpointConfig, callers need to change nothing.import boto3
sm = boto3.client("sagemaker")
# 1) Model: artifact + container
sm.create_model(
ModelName="churn-model",
PrimaryContainer={"Image": image_uri, "ModelDataUrl": "s3://bkt/model.tar.gz"},
ExecutionRoleArn=role,
)
# 2) EndpointConfig: instance type/count
sm.create_endpoint_config(
EndpointConfigName="churn-config",
ProductionVariants=[{
"VariantName": "AllTraffic",
"ModelName": "churn-model",
"InstanceType": "ml.m5.xlarge",
"InitialInstanceCount": 2,
}],
)
# 3) Endpoint: the actual deployment
sm.create_endpoint(EndpointName="churn-endpoint", EndpointConfigName="churn-config")The real value of this three-layer separation lies in zero-downtime updates. When you deploy a new model, you create a new EndpointConfig and call update_endpoint; SageMaker first brings up new instances and has them pass health checks, then moves traffic over and takes the old instances down (Blue/Green). The endpoint stays alive throughout, so callers experience no downtime. By adjusting ProductionVariant weights you can also split traffic between two models on the same endpoint for A/B testing or a canary deployment.
If you delete an endpoint and recreate it when putting up a new model, the address is cut off. The correct procedure is create a new EndpointConfig → update_endpoint.
[Before update] Endpoint(churn-endpoint) ──▶ Config v1 ──▶ 2 instances (old model)
update_endpoint(EndpointConfigName="config-v2")
│
├─ 1) Provision new instances (green) + load the model
├─ 2) Wait for health checks to pass
├─ 3) Shift traffic to green (all at once / canary / linear)
├─ 4) Alarm monitoring window (baking) — automatic rollback on failure
└─ 5) Terminate the old instances (blue)
[After update] Endpoint(churn-endpoint) ──▶ Config v2 ──▶ 2 instances (new model)
↑ The address stays the same. Callers change nothing# Swap in the new configuration — keep the endpoint name as it is
sm.update_endpoint(
EndpointName="churn-endpoint",
EndpointConfigName="churn-config-v2",
)
# Check the transition status: Updating → InService
status = sm.describe_endpoint(EndpointName="churn-endpoint")["EndpointStatus"]The traffic shifting methods (deployment guardrails) differ in character.
| Shifting method | Behavior | When to use |
|---|---|---|
| All-at-once | Moves all traffic to the new version in one step | When risk is low and you want to finish quickly |
| Canary | Sends only a small share (e.g., 5%) first, then the rest after observing | When the new model is risky and you want to minimize the blast radius |
| Linear | Moves traffic in steps of a fixed proportion | When you want to watch load and error rate gradually |
| Rolling | Replaces existing capacity a portion at a time | When you cannot afford to double the full capacity |
⚠️ Pitfall: The answer to "deploy a new model without downtime" is always a new EndpointConfig +
update_endpoint. ① Deleting and recreating the endpoint cuts the address and causes downtime, ② creating only a new Model resource is not automatically reflected in the existing endpoint, and ③ connecting directly to a managed instance to change files is an anti-pattern that is impossible in the first place. These three repeatedly appear as wrong-answer options.
You can place several ProductionVariants inside one EndpointConfig.
InitialVariantWeight, traffic is distributed in proportion to the weights.ProductionVariants=[
{"VariantName": "ModelA", "ModelName": "model-a",
"InstanceType": "ml.m5.xlarge", "InitialInstanceCount": 2,
"InitialVariantWeight": 9}, # 90% of traffic
{"VariantName": "ModelB", "ModelName": "model-b",
"InstanceType": "ml.m5.xlarge", "InitialInstanceCount": 1,
"InitialVariantWeight": 1}, # 10% of traffic
]A/B testing and shadow testing are distinguished by whether the user receives the new model's response.
[A/B test] Request ──┬─ 90% ─▶ ModelA ─▶ Response returned to the user
└─ 10% ─▶ ModelB ─▶ Response returned to the user ← some users are affected
[Shadow] Request ────────▶ ModelA ─▶ Response returned to the user
└(copy)──▶ ModelB ─▶ Response discarded, only metrics recorded ← zero user impact| Aspect | A/B (weighted distribution) | Shadow testing |
|---|---|---|
| Traffic | Splits the real requests | Sends a copy of the real requests |
| New model response | Returned to the user | Discarded (only metrics collected) |
| User impact | Yes (some users) | None |
| Purpose | Compare business metrics | Risk-free performance and stability validation |
SageMaker can also force a specific variant with the TargetVariant parameter when calling InvokeEndpoint. This is used when you want to test only a particular model regardless of the weights. In addition, the shadow testing (shadow variant) feature sends a copy of production traffic to the new model but throws away the response, so you can validate the new model's performance without affecting real users. Tell A/B (weighted distribution) and shadow (response discarded) apart by that difference.
A real-time endpoint attaches Application Auto Scaling to adjust the instance count automatically with traffic. The most common policy is target tracking, which scales instances out and in to hold a given metric at a target value.
The representative metric is SageMakerVariantInvocationsPerInstance (invocations per second per instance). If you set a target such as "I want each instance to handle 1,000 requests per second," it scales out when traffic grows and exceeds this value, and scales in when it falls.
aas = boto3.client("application-autoscaling")
resource_id = "endpoint/churn-endpoint/variant/AllTraffic"
aas.register_scalable_target(
ServiceNamespace="sagemaker",
ResourceId=resource_id,
ScalableDimension="sagemaker:variant:DesiredInstanceCount",
MinCapacity=2, MaxCapacity=10,
)
aas.put_scaling_policy(
PolicyName="invocations-tracking",
ServiceNamespace="sagemaker", ResourceId=resource_id,
ScalableDimension="sagemaker:variant:DesiredInstanceCount",
PolicyType="TargetTrackingScaling",
TargetTrackingScalingPolicyConfiguration={
"TargetValue": 1000.0,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "SageMakerVariantInvocationsPerInstance"
},
"ScaleInCooldown": 300, "ScaleOutCooldown": 60,
},
)MinCapacity must be 1 or more, so a real-time endpoint does not shrink to 0 (if you need 0, use serverless/asynchronous).ScaleOutCooldown short → react quickly to rising loadScaleInCooldown long → so you don't scale in too hastily and regret it when traffic spikes againScaling policy types differ by purpose.
| Policy type | Behavior | Suitable situation |
|---|---|---|
| Target tracking | Automatically adds or removes capacity to hold a metric at the target | The default choice. Adjusts in proportion to load |
| Step scaling | Adds or removes a set amount per alarm-threshold band | When different adjustment sizes are needed per band |
| Scheduled scaling | Changes capacity in advance at set times | Predictable surges such as sales or events |
⚠️ Pitfall: Auto Scaling is not a cure-all. It takes several minutes to bring up a new instance, load the model, and pass the health check, so it cannot respond instantly to a sudden traffic spike. For predictable surges such as Black Friday, you must increase capacity ahead of time with scheduled scaling or secure a sufficient
MinCapacity. The answer to the scenario "we turned Auto Scaling on, yet latency jumped during the spike" is usually scheduled scaling or a higher minimum capacity.
You need to know what to look at when deciding on scaling and tuning. Endpoint metrics are emitted to CloudWatch.
| Metric | Meaning | If this value jumps |
|---|---|---|
Invocations | Total number of invocations the endpoint received | A rise or fall in traffic itself |
InvocationsPerInstance | Invocations per instance | The reference metric for target tracking scaling |
ModelLatency | Time the model container took to respond | A sign that the model or instances are insufficient |
OverheadLatency | Time added by SageMaker-side processing | A problem in payload serialization or the network |
Invocation4XXErrors | Bad requests (format, payload) | A caller-side input schema problem |
Invocation5XXErrors | Model or container errors | An inference code exception, OOM, etc. |
CPUUtilization / MemoryUtilization | Instance resource utilization | Consider a larger instance type or scaling out |
When looking at latency problems, you must look at ModelLatency and OverheadLatency separately. If ModelLatency is high, the model itself is heavy or the instances are insufficient, so the answer is a bigger instance, scaling out, or model optimization. If OverheadLatency is high, large-payload serialization or the network segment is the likely cause. If you lump the two together as "it's slow," you will take the wrong action.
The choice of instance family depends on the model type and the latency requirement.
| Family | Character | Suitable models | Notes |
|---|---|---|---|
ml.m5 / ml.c5 (CPU) | General-purpose / compute-optimized | Traditional ML such as XGBoost, linear models, small neural networks | Cheapest. The default for most tabular-data models |
ml.g4dn / ml.g5 (GPU) | Inference GPUs | Medium and large image/NLP deep learning | Parallelizes matrix operations to cut latency significantly |
ml.p3 / ml.p4 (high-performance GPU) | Large training GPUs | Very large models, ultra-high throughput | Expensive. Commonly used for training rather than inference |
ml.inf1 / ml.inf2 (Inferentia) | AWS inference-dedicated chips | Deep learning inference (transformers, CNNs) | Lower cost per inference. Requires a Neuron compilation step |
Choosing an inference instance is a balance of "latency target × throughput × cost." Traditional ML (XGBoost) is fine on CPU, and attaching a GPU brings little benefit. Deep learning such as transformers and CNNs, on the other hand, sees latency drop dramatically on GPU or Inferentia. If the exam gives the condition "a deep learning model, but GPU cost is a burden," that is the signal for Inferentia (inf1/inf2). Conversely, "it's XGBoost, so let's cut cost by using a GPU" is easily used as a wrong option.
If it is hard to choose the instance type and count yourself, SageMaker Inference Recommender automatically runs load tests and recommends the optimal configuration based on cost, latency, and throughput. It deploys the model to several instance types, sends traffic through them, and compares the results.
| Job type | What it does | When to use |
|---|---|---|
| Default | Quickly deploys to several instance types for a broad comparison | A first-pass exploration to narrow the candidates |
| Advanced (custom) | You define the traffic pattern (request rate, latency SLA, etc.) for a precise load test | When you need to confirm that the real SLA is met |
sm.create_inference_recommendations_job(
JobName="rec-job-1",
JobType="Default",
RoleArn=role,
InputConfig={"ModelPackageVersionArn": model_package_arn},
)Inference Recommender has two modes. A Default job deploys quickly to several instance types and compares them broadly, while an Advanced (custom) job lets you define the traffic pattern you want (requests per second, latency SLA) for a precise load test. The answer to the scenario "I don't know how to choose the instance type, and I want to decide with data" is Inference Recommender.
| Symptom | Cause | Action |
|---|---|---|
| Fine in normal times, but latency jumps only during spikes | New instance startup and model load take several minutes | Secure capacity in advance with scheduled scaling; raise MinCapacity |
ModelLatency stays high | The model is heavy or instances are insufficient | Larger instance / scale out; consider GPU or Inferentia |
Invocation5XXErrors increase | Inference code exception, out of memory (OOM) | Check container logs; switch to an instance with more memory |
| The instance count keeps going up and down | Scale-in cooldown is too short | Increase ScaleInCooldown to suppress flapping |
| Costs are incurred even at night with no traffic | Real-time always keeps at least 1 instance | For intermittent traffic, move to serverless or asynchronous |
| Error rate rose after deployment and you want to roll back | New-model regression | Configure automatic rollback with CloudWatch alarms + canary/linear shifting |
The next article takes a deep look at multi-model/multi-container endpoints that put several models on one endpoint to cut cost, plus inference pipelines and Inferentia/Elastic Inference.
model.tar.gz) holding the trained model's weights and structure, uploaded to S3.Click a choice to reveal the answer and explanation.
Question 1
You want to deploy a new model version to a live real-time endpoint without callers experiencing downtime. What is the correct method?
Question 2
You want to apply autoscaling to a real-time endpoint whose traffic varies greatly by time of day. What is the most commonly used target tracking metric?
Question 3
You deploy an XGBoost-based churn prediction model in real time. The latency requirement is typical and you want to save cost. What is the most appropriate instance choice?
Question 4
You want to validate a new model on production traffic while observing only the new model's performance, without affecting real users' responses. What is the appropriate feature?
Question 5
You want to decide, based on data, which instance type and count are optimal in terms of cost, latency, and throughput. Which SageMaker tool should you use?