Reference sheet · machine-learning platform

sagemaker v3

sagemaker 3.8  ·  core · train · serve · mlops  ·  the Python SDK, not the console

SageMaker Python SDK v3 is a ground-up rewrite. The framework-specific estimators and models are gone: one ModelTrainer trains everything, one ModelBuilder deploys everything, and structured config objects replace the old kwargs soup. Underneath sits sagemaker.core — a typed, object-oriented mirror of every SageMaker API resource. Author with the high-level classes; drop to core when you need the raw resource.

setup · session · images sagemaker.core train — ModelTrainer fine-tuning (v3-only) serve — ModelBuilder mlops · pipelines v2→v3 · gotcha most common

Verified July 2026 against the SageMaker Python SDK v3 documentation (Overview, Training, Inference, MLOps, Model Customization) and the v3.0.0 release notes.  ·  sagemaker 3.8.0 (16 Apr 2026), sagemaker-core 2.13.1  ·  Python ≥3.10.  ·  v3 has breaking changes from v2 — almost every SageMaker cheat sheet online still teaches Estimator, Model and Predictor, none of which are the v3 way.

Mental model — four packages, two authoring classes, and the typed resource layer they all sit on
A · THE EVERYDAY FLOW — TRAIN, THEN DEPLOY SourceCode Compute · InputData config objects ModelTrainer .train(input_data_config) one class, every framework TrainingJob runs on ml.* instances → model.tar.gz in S3 ModelBuilder .build() · .deploy() model=trainer → no glue model=trainer Endpoint .invoke(body=...) real-time · serverless predictions JSON · CSV B · THE FOUR PACKAGES — WHAT TO IMPORT FROM WHERE sagemaker.train ModelTrainer · Compute SourceCode · InputData distributed · tuner the training half sagemaker.serve ModelBuilder InferenceSpec · SchemaBuilder ModelServer · Mode the inference half sagemaker.mlops Pipeline · steps feature_store model registry · monitoring stitch it into production sagemaker.core resources: TrainingJob, Model, Endpoint, TransformJob … session · image_uris · lineage typed mirror of every API every high-level class is a thin, ergonomic wrapper over a sagemaker.core resource TrainingJob.create(...) · Model.get(...) · Endpoint.get_all() — full API parity, intelligent defaults, resource chaining C · V3-EXCLUSIVE — FOUNDATION-MODEL FINE-TUNING Specialised trainers that simply do not exist in v2 SFTTrainer supervised · DPOTrainer preference · RLAIFTrainer AI-feedback RL · RLVRTrainer verifiable-reward RL LoRA · preference optimisation · RLHF — serverless, months-to-days, evaluators and datasets built in
↔ swipe to see the whole diagram
Train a model and deploy it — the whole v3 arc in one screen
# pip install "sagemaker>=3.8"   —   explicit imports from the four subpackages
from sagemaker.train import ModelTrainer
from sagemaker.train.configs import SourceCode, Compute, InputData
from sagemaker.serve import ModelBuilder
from sagemaker.core.helper.session_helper import get_execution_role

trainer = ModelTrainer(                              # ★ one class replaces every *Estimator
    training_image="...pytorch-training:2.3-gpu-py311",
    role=get_execution_role(),
    source_code=SourceCode(source_dir="./src", entry_script="train.py"),
    compute=Compute(instance_type="ml.g5.xlarge", instance_count=1),
    hyperparameters={"epochs": 10, "lr": 3e-4},
)
trainer.train(input_data_config=[InputData(channel_name="train",   # not .fit()
                                          data_source="s3://bkt/train")])

mb = ModelBuilder(model=trainer)                     # ★ hand the trainer straight over
mb.build()
endpoint = mb.deploy(endpoint_name="my-ep", instance_type="ml.m5.xlarge",
                     initial_instance_count=1)
out = endpoint.invoke(body='{"inputs": [[1,2,3,4]]}',           # not predictor.predict()
                      content_type="application/json")
Part ISetup & the core resource layer install · session · roles · image URIs · sagemaker.core
01Install — and the package split

sagemaker 3.8.0 · Python ≥3.10

  • pip install "sagemaker>=3.8"The umbrella package. It pulls in sagemaker-core, -train, -serve and -mlops together.
  • pip install "sagemaker[train,serve,mlops,all]"Extras exist if you want only part of the stack — e.g. a training image that shouldn't carry the serving deps.
  • pip install sagemaker-coreThe low-level SDK on its own. Standalone install makes sense in a Lambda or a thin client that only reads or launches resources.
  • import sagemaker; sagemaker.__version__Check this first when a snippet fails: anything below 3.0 is a different SDK. v2 tops out around 2.24x.
  • # v3 removed the bare `import sagemaker` styleImport explicitly from the subpackages instead — from sagemaker.train import ModelTrainer, not sagemaker.estimator.Estimator.changed
  • pip install "sagemaker[train]" torch # torch is no longer a hard depSince 3.8 PyTorch is not pinned by the SDK — install the framework you actually use.3.8
02Session, region & role

everything moved under sagemaker.core.helper

  • from sagemaker.core.helper.session_helper import Session, get_execution_roleThe v2 sagemaker.Session() and top-level get_execution_role() both moved here.moved
  • session = Session(); region = session.boto_region_nameWraps the boto3 session and resolves the default bucket, region and config.
  • role = get_execution_role()Inside Studio or a notebook this returns the attached role. Locally it fails — pass a role ARN string instead.gotcha
  • session.default_bucket()sagemaker-{region}-{account}, created on demand. Overridable with default_bucket_prefix.
  • # the role needs AmazonSageMakerFullAccessPlus S3 access to your data buckets, and iam:PassRole so jobs can assume it. The single most common permissions failure.
  • PipelineSession() # from core.workflow.pipeline_contextA session variant that defers job launches into pipeline steps rather than running them immediately — use it when building a Pipeline.
03Container image URIs

the prebuilt DLC you train and serve in

  • from sagemaker.core import image_urisWas sagemaker.image_uris in v2. Same idea, new home.moved
  • image_uris.retrieve(framework="pytorch", region=region, version="2.3", py_version="py311", instance_type="ml.g5.xlarge", image_scope="training")Resolves the exact AWS Deep Learning Container URI. image_scope is training or inference.
  • image_scope="inference"The serving image differs from the training one — passing the wrong scope is a frequent deploy-time error.gotcha
  • framework="sklearn", version="1.2-1"Also xgboost, huggingface, tensorflow, djl-lmi (large-model inference), djl-neuronx.
  • # bring your own ...dkr.ecr.{region}.amazonaws.com/my:tagAny ECR image works. SageMaker only requires the container honour its training / serving contract.
04sagemaker.core resources

a typed object per SageMaker API resource

  • from sagemaker.core.resources import TrainingJob, Model, Endpoint, TransformJobThis layer replaces reaching for boto3.client("sagemaker"). Full API parity, but typed and object-oriented.replaces boto3
  • job = TrainingJob.create(training_job_name="j1", role_arn=role, ...)Every resource has static .create(). Returns the object, already populated.
  • Endpoint.get(endpoint_name="my-ep")  ·  Endpoint.get_all().get() fetches one, .get_all() lists. Attributes are real fields, so autocompletion works.
  • job.wait()  ·  job.refresh()  ·  job.stop()  ·  ep.delete()Lifecycle methods live on the object. refresh() re-reads current status from the service.
  • # resource chaining model.create_endpoint(...)Methods that return the next resource, so you rarely thread ARNs by hand.
  • # intelligent defaultsRegion, role and bucket fill in from the session and a config file, so .create() calls stay short.
05Config & intelligent defaults

stop repeating role and network config

  • # config.yaml SchemaVersion: '1.0' SageMaker: PythonSDK: Modules: Session: DefaultS3Bucket: my-bucketSet org-wide defaults for role, VPC, KMS key, tags and bucket once.
  • export SAGEMAKER_USER_CONFIG_OVERRIDE=/path/config.yamlPoints the SDK at your file; an admin default and a user file are layered.
  • EnableNetworkIsolation · VpcConfig · VolumeKmsKeyIdSecurity-relevant knobs best set in config, not sprinkled across code, so every job inherits them.
  • # precedence explicit arg > user config > admin config > SDK defaultAn argument you pass always wins over the file.
  • session.sagemaker_configInspect what was actually loaded — the quickest way to debug "why did my job get that role".
06Local & in-process modes

iterate without paying for ml.* instances

  • from sagemaker.train.model_trainer import Mode training_mode=Mode.LOCAL_CONTAINERRuns the training job in Docker on your machine. Needs Docker running; same container as the cloud.
  • Compute(instance_type="local_cpu") # or "local_gpu"Local data paths are mounted straight into the container; artifacts land in the working directory.
  • from sagemaker.serve.mode.function_pointers import Mode mode=Mode.IN_PROCESSServe entirely inside your Python process — no container, no AWS call. Ideal for a fast unit test of InferenceSpec.v3
  • mb.deploy_local(endpoint_name="local-ep")The local counterpart to deploy(), for both in-process and local-container modes.
  • mode=Mode.LOCAL_CONTAINER # serving sideSame serving container image as production, so a model that works here works on the endpoint.
  • # the ladder in-process → local container → cloudClimb it in order: each rung catches a different class of bug at a lower cost.
Part IITraining & fine-tuning ModelTrainer · configs · distributed · tuning · the v3-only trainers
07ModelTrainer

one class replaces every *Estimator

  • from sagemaker.train import ModelTrainerReplaces Estimator, PyTorch, TensorFlow, HuggingFace, SKLearn, XGBoost — all of them.replaces
  • trainer = ModelTrainer(training_image=img, role=role, compute=..., source_code=...)The framework is decided by the image, not the class. That is the whole design shift.
  • trainer.train(input_data_config=[InputData(...)])Not .fit(). Takes a list of InputData channels rather than a dict.changed
  • hyperparameters="hyperparameters.json" # or .yaml, or a dictFile-based hyperparameters version-control cleanly and support nested structures; reach the script as CLI args and via SM_HPS.
  • ModelTrainer.from_jumpstart_config(JumpStartConfig(model_id="..."))Auto-configures image, instance type and proven default hyperparameters for a JumpStart model.
  • base_job_name="exp-a"  ·  trainer.train(wait=False)wait=False returns immediately; poll the returned job or move on.
08The config objects

structured configs, not a kwargs pile

  • from sagemaker.train.configs import SourceCode, Compute, InputData, StoppingConditionv2's flat estimator arguments are now typed objects you compose.
  • SourceCode(source_dir="./src", entry_script="train.py", requirements="requirements.txt")Replaces entry_point + source_dir. command= instead runs a raw shell command in the container.
  • Compute(instance_type="ml.g5.xlarge", instance_count=2, volume_size_in_gb=100)Was instance_type=/instance_count= on the estimator. Also carries keep_alive_period_in_seconds for warm pools.
  • InputData(channel_name="train", data_source="s3://bkt/train")Replaces TrainingInput. One per channel; the script reads them under /opt/ml/input/data/{channel}.
  • StoppingCondition(max_runtime_in_seconds=3600)Replaces the bare max_run=. Cap it — a hung job otherwise bills to the ceiling.
  • OutputDataConfig(s3_output_path="s3://bkt/out")Where model.tar.gz and other artifacts land. Defaults to the session bucket if omitted.
09The training script contract

what runs inside the container

  • /opt/ml/input/data/{channel} # your InputData channelsEach channel name becomes a directory. Read from it like any local path.
  • /opt/ml/model/ # save the model hereEverything written here is tarred into model.tar.gz and uploaded. Miss it and your artifact is empty.gotcha
  • import os; os.environ["SM_HPS"]Hyperparameters as a JSON string. Also SM_MODEL_DIR, SM_CHANNEL_TRAIN, SM_NUM_GPUS.
  • /opt/ml/output/data/ # extra non-model outputsFor evaluation reports and figures — uploaded separately from the model artifact.
  • # metrics via regex print(f"loss: {v}")SageMaker scrapes stdout with metric_definitions regexes; that is how tuning reads your objective.
  • /opt/ml/checkpoints/ # synced to S3 during the runWrite checkpoints here so a Spot interruption resumes instead of restarting.
10Distributed training

drivers on top of ModelTrainer

  • from sagemaker.train.distributed import Torchrun distributed=Torchrun(process_count_per_node=8)Wraps torchrun for multi-GPU / multi-node PyTorch. Pair with instance_count>1.
  • MPI(process_count_per_node=4)The MPI driver, for Horovod and other MPI-based frameworks.
  • Compute(instance_count=2) # local_cpu for a dry runTwo local containers reproduce multi-node coordination before you spend on real GPUs.
  • class CustomDriver(DistributedConfig): ...Extend DistributedConfig, implement driver_dir and driver_script, for a bespoke launcher.
  • SM_DISTRIBUTED_CONFIG · SM_HPS · SM_SOURCE_DIREnv vars your driver script reads to coordinate the processes.
  • # data sharding InputData(..., s3_data_distribution_type="ShardedByS3Key")Splits the data across nodes instead of replicating the whole set to each.
11Hyperparameter tuning

search over ModelTrainer runs

  • from sagemaker.train.tuner import HyperparameterTunerv2's sagemaker.tuner.HyperparameterTuner moved into train.moved
  • from sagemaker.core.parameter import ContinuousParameter, CategoricalParameter, IntegerParameterThe range types now live in core.parameter.
  • HyperparameterTuner(model_trainer=trainer, objective_metric_name="val:loss", ...)Takes a model_trainer=, not an estimator. Everything else — ranges, strategy — is familiar.
  • hyperparameter_ranges={"lr": ContinuousParameter(1e-4, 1e-1)}Log-scaled where it matters; CategoricalParameter([32, 64, 128]) for discrete choices.
  • strategy="Bayesian"  ·  max_jobs=20, max_parallel_jobs=3Bayesian learns between jobs; Random/Grid/Hyperband also available. Parallelism trades cost for wall-clock.
  • tuner.tune(inputs=[InputData(...)]); tuner.best_training_job()Kick off the search, then pull the winner to deploy.
12Fine-tuning trainers

v3-exclusive — no v2 equivalent

  • SFTTrainer # supervised fine-tuningTask-specific adaptation on labelled prompt/response pairs — the usual starting point.
  • DPOTrainer # direct preference optimizationAligns to chosen-vs-rejected preference pairs without the RL machinery of RLHF.
  • RLVRTrainer # RL from verifiable rewardsFor tasks with a checkable answer (maths, code) where correctness is the reward signal.
  • RLAIFTrainer # RL from AI feedbackUses a model, not humans, to score outputs — scales preference data cheaply.
  • # techniques LoRA · preference optimisation · RLHFAdvanced methods that "simply don't exist in v2", per the docs. Training is serverless — no instance juggling.v3
  • # Nova + open-weightCustomise Amazon Nova models or open-weight models; evaluators and curated datasets are built in.
13Model evaluation

judge a customised model before shipping

  • # LLM-as-JudgeScore generations with a stronger model as the grader — built into the customisation flow.
  • # InspectAI evaluationStructured evals via the InspectAI framework, wired into SageMaker.
  • # custom scorerBring your own scoring function when neither a judge model nor a benchmark fits.
  • # benchmark evaluationRun standard benchmarks against the tuned model for an apples-to-apples baseline.
  • # evaluators are first-classEvaluation is part of the customisation lifecycle, not a bolt-on script — results feed the deploy decision.
14Deploy a customised model

endpoint, or straight to Bedrock

  • mb = ModelBuilder(model=customized_model); mb.deploy(...)A tuned model deploys through the same ModelBuilder path as any other.
  • BedrockModelBuilder(...) # deploy to Amazon BedrockPush an open-weight customised model into Bedrock for managed, serverless invocation.v3
  • accept_eula=TrueGated foundation models require explicit EULA acceptance or the deploy is refused.gotcha
  • # evaluate → deploy in one flowCustomisation, evaluation and deployment share objects, so promising checkpoints move forward without re-plumbing.
  • # serverless customisationThe managed infra means you go from proof-of-concept to a deployed custom model without provisioning training clusters.
15AWS Batch training queues

queue jobs, let Batch schedule them

  • from sagemaker.train.aws_batch.training_queue import TrainingQueueSubmit ModelTrainer jobs into an AWS Batch queue for automatic scheduling.v3
  • queue = TrainingQueue("my-fifo-jq"); queue.submit(training_job=trainer, inputs=None)Batch manages capacity and execution order; you stop babysitting instance limits.
  • # FIFO or priority schedulingPick ordering by queue type — fair-share FIFO, or priority when some experiments jump the line.
  • create_resources(resource_manager, job_queue_name=..., max_capacity=4)Provision the Service Environment and Job Queue programmatically, or set them up once in the console.
  • # good for sweeps · shared GPU pools · bursty teamsWhere many jobs contend for limited capacity, a queue beats manual retries on ResourceLimitExceeded.
Part IIIInference with ModelBuilder build · deploy · invoke · InferenceSpec · modes · optimisation
16ModelBuilder

one class replaces every *Model

  • from sagemaker.serve import ModelBuilderReplaces Model, PyTorchModel, HuggingFaceModel, SKLearnModel and the rest.replaces
  • mb = ModelBuilder(model=trainer)Train-to-deploy: hand a ModelTrainer straight in and skip the artifact plumbing entirely.
  • ModelBuilder(model="my-model", model_path="s3://bkt/model.tar.gz")Or point at an existing artifact. model= also accepts a HuggingFace hub id or a JumpStart id.
  • core_model = mb.build(model_name="m1")build() assembles the deployable model and returns a core.resources.Model. Separate step from deploy.changed
  • ModelBuilder.from_jumpstart_config(JumpStartConfig(model_id="..."))Deploy a JumpStart model with its curated serving defaults.
  • ModelBuilder(model=[m1, m2]) # serial inference pipelineA list of models becomes a multi-container pipeline — e.g. sklearn preprocess → xgboost predict.
17Deploy & invoke

the method names changed — relearn them

  • ep = mb.deploy(endpoint_name="my-ep", instance_type="ml.m5.xlarge", initial_instance_count=1)Returns a core.resources.Endpoint, not a Predictor.changed
  • ep.invoke(body=data, content_type="application/json")Not predictor.predict(data). You pass bytes and a content type; you get bytes back.
  • # serializers are gone json.dumps(payload)v2's serializers/deserializers are removed — handle encoding yourself with json/csv.removed
  • initial_instance_count=2 # behind a load balancerMore than one instance for availability and throughput; SageMaker balances across them.
  • ServerlessInferenceConfig(memory_size_in_mb=2048, max_concurrency=5)Scale-to-zero serverless for spiky, low-volume traffic — no idle instance cost.
  • Endpoint.get("my-ep").delete() # stop the meterA real-time endpoint bills per hour while it exists. Deleting it is the number-one way to avoid a surprise bill.gotcha
18InferenceSpec & SchemaBuilder

custom load and predict logic

  • class MySpec(InferenceSpec): def load(self, model_dir): ... def invoke(self, input_object, model): ...load() deserialises the model once; invoke() runs each prediction. The v3 replacement for a custom inference.py.
  • SchemaBuilder(sample_input, sample_output)Give one example each way; the SDK infers marshalling for the endpoint. Required for custom specs.
  • ModelBuilder(inference_spec=MySpec(), schema_builder=sb, model_server=ModelServer.TORCHSERVE)Wire the spec, schema and server together.
  • from sagemaker.serve.utils.types import ModelServerTORCHSERVE, MMS (multi-model), DJL_SERVING, TENSORFLOW_SERVING, TRITON.
  • def load(self, model_dir): return torch.jit.load(f"{model_dir}/model.pth")Same InferenceSpec runs in-process, in a local container, and on the endpoint — test cheap, ship unchanged.
19Model optimisation

quantise before you deploy

  • mb.optimize(instance_type="ml.g5.2xlarge", quantization_config={...})Runs an optimisation job and returns an optimised model ready to deploy.
  • quantization_config={"OverrideEnvironment": {"OPTION_QUANTIZE": "awq"}}AWQ, plus other schemes depending on the container — shrinks a large model's memory and latency.
  • accept_eula=TrueRequired for gated models such as Llama. Omit it and the job is refused.gotcha
  • mb.deploy(endpoint_name="llama-ep", initial_instance_count=1)Deploy the optimised artifact exactly as any other.
  • # when LLMs · tight latency budgets · smaller instancesQuantisation often lets a model fit on a cheaper GPU tier — a direct cost lever.
20Batch transform

offline inference, no live endpoint

  • from sagemaker.core.transformer import Transformerv2's sagemaker.transformer.Transformer moved into core.moved
  • Transformer(model_name="m", instance_count=1, instance_type="ml.m5.xlarge", output_path="s3://bkt/out")Runs the model over a whole S3 dataset, writes results to S3, then tears down. No standing cost.
  • transformer.transform("s3://bkt/in", content_type="text/csv", split_type="Line")split_type chunks the input; assemble_with="Line" reassembles the output.
  • input_filter="$[1:]"  ·  output_filter="$"  ·  join_source="Input"JSONPath filters drop an id column before inference and re-join it after.
  • # choose batch over real-time whenThe workload is periodic and latency doesn't matter — nightly scoring, backfills, one-off evaluation.
21Serving modes at a glance

pick the cheapest that fits the traffic

  • Mode.SAGEMAKER_ENDPOINT # real-timeAlways-on, low latency, per-hour billing. The default for online serving.
  • ServerlessInferenceConfig(...)Scale-to-zero. Cold starts, but nothing to pay when idle — spiky or low-volume APIs.
  • Transformer(...).transform(...) # batchLarge offline datasets, no endpoint. Cheapest per prediction at volume.
  • # async inference AsyncInferenceConfig(...)Queue large payloads or long-running requests; results land in S3. Good for big inputs and minute-scale latency.
  • Mode.IN_PROCESS  ·  Mode.LOCAL_CONTAINERDev only — validate the spec before any of the above touches AWS.
  • # multi-model endpointHost many models behind one endpoint to amortise instance cost when each model is small or rarely hit.
Part IVMLOps, migration & the traps pipelines · processing · registry · feature store · v2→v3 · gotchas
22Pipelines

orchestrate the whole workflow

  • from sagemaker.mlops.workflow.pipeline import Pipelinev2's sagemaker.workflow.pipeline.Pipeline moved under mlops.moved
  • from sagemaker.mlops.workflow.steps import ProcessingStep, TrainingStepPlus ModelStep, TuningStep, EMRServerlessStep, CacheConfig.
  • step_train = TrainingStep(name="Train", step_args=trainer.train())Key pattern: under a PipelineSession, calling .train() or .run() yields step_args instead of launching.
  • pipeline = Pipeline(name="p", steps=[step_process, step_train, step_register])Dependencies infer from data flow, or pin them with depends_on=.
  • pipeline.upsert(role_arn=role); pipeline.start()upsert creates or updates the definition; start triggers a run. Parameterise with ParameterString.
  • ConditionStep(condition=ModelAccuracyCondition(threshold=0.85), if_steps=..., else_steps=...)Branch the DAG — deploy only if the model clears the bar, else retrain.
23Processing jobs

preprocess, evaluate, post-process

  • from sagemaker.core.processing import ScriptProcessor, FrameworkProcessorThe v2 SKLearnProcessor and friends collapse into ScriptProcessor plus an image.replaces
  • ScriptProcessor(image_uri=img, instance_type="ml.m5.xlarge", instance_count=1, role=role)Runs any script in a container over S3 data — feature engineering, evaluation, batch cleanup.
  • from sagemaker.core.shapes import ProcessingInput, ProcessingS3Input, ProcessingOutput, ProcessingS3OutputI/O is now a nested ProcessingInput(s3_input=ProcessingS3Input(...)) rather than flat kwargs.changed
  • /opt/ml/processing/input · /opt/ml/processing/outputThe in-container mount points your script reads and writes, mirroring the training contract.
  • processor.run(inputs=[...], outputs=[...], code="preprocess.py", arguments=[...])Under a PipelineSession this returns step_args for a ProcessingStep.
24Model registry & Clarify

version, approve, and audit

  • mb.register(model_package_group_name="prod", approval_status="PendingManualApproval")Registration is a method on ModelBuilder now, not a separate RegisterModel class.changed
  • ModelPackage.get(model_package_name=arn)Pull a registered version back to deploy it — the registry is the hand-off point to production.
  • approval_status="Approved"Gate deployment on approval; a pipeline or a human flips the status.
  • from sagemaker.core.clarify import SageMakerClarifyProcessor, BiasConfig, SHAPConfigPre- and post-training bias metrics plus SHAP explainability.
  • clarify.run_pre_training_bias(data_config=..., data_bias_config=BiasConfig(...), methods=["CI", "DPL"])Class-imbalance and label-skew before you even train — catch a biased dataset early.
  • # lineage Context · Action · Artifact · AssociationFrom core.lineage — a graph tracing data → job → model → endpoint for audit.
25Feature Store

shared, point-in-time-correct features

  • from sagemaker.mlops.feature_store import FeatureGroupManager, FeatureDefinition, FeatureTypeEnumv2's feature_group.FeatureGroup becomes FeatureGroupManager under mlops.moved
  • FeatureGroupManager.create(feature_group_name=..., record_identifier_feature_name="id", event_time_feature_name="ts", ...)Every group needs a record identifier and an event-time feature — that pair enables point-in-time joins.
  • OnlineStoreConfig(enable_online_store=True)Online store for low-latency lookups at inference; offline store on S3 for training sets.
  • offline_store_config=OfflineStoreConfig(..., table_format="Iceberg")Iceberg tables with compaction and snapshot-expiry properties — new in the v3 Feature Store.3.8
  • LakeFormationConfig(enabled=True, ...)Column- and row-level access control on offline data, opt-in at group creation.3.8
  • FeatureGroup.get_all() # from core.resourcesThe low-level resource for listing and inspecting existing groups.
26Migrating v2 → v3: imports

the class-name Rosetta stone

  • sagemaker.estimator.Estimator → sagemaker.train.ModelTrainerEvery framework estimator (PyTorch, TensorFlow, HuggingFace, SKLearn, XGBoost) collapses to this one.
  • sagemaker.model.Model → sagemaker.serve.ModelBuilderLikewise every *Model class becomes ModelBuilder.
  • sagemaker.predictor.Predictor → sagemaker.core.resources.EndpointAnd Transformercore.resources.TransformJob / core.transformer.Transformer.
  • sagemaker.session.Session → sagemaker.core.helper.session_helper.SessionSame for get_execution_role and image_uris.retrieve — all under core now.
  • sagemaker.workflow.* → sagemaker.mlops.workflow.*Pipeline and the step classes; ParameterString and PipelineSession live in core.workflow.
  • boto3.client("sagemaker") → sagemaker.core.resources.*Reach for the typed resource instead of raw boto3 whenever one exists.
27Migrating v2 → v3: methods

the calls whose shape changed

  • estimator.fit({"train": "s3://..."}) → trainer.train(input_data_config=[InputData(...)])fittrain, and a dict of channels becomes a list of InputData.
  • predictor.predict(data) → endpoint.invoke(body=data, content_type="application/json")Different verb, and you pass a content type explicitly.
  • instance_type="..." → Compute(instance_type="...")Loose kwargs become config objects: entry_pointSourceCode, max_runStoppingCondition.
  • model.deploy() returns Predictor → returns EndpointAnd build() is now a distinct step before deploy().changed
  • serializers / deserializers → json.dumps / json.loadsDo the (de)serialisation yourself; the helper classes are gone.removed
  • # migrate incrementallyv2 and v3 are different import paths — you can port one workflow at a time rather than all at once.
28Cost & safety traps

what silently bills or breaks

  • Endpoint.get("ep").delete()A real-time endpoint bills every hour it exists, prediction traffic or not. Delete what you're not using.
  • StoppingCondition(max_runtime_in_seconds=...)Always cap training runtime; a wedged job otherwise runs to the account limit on GPU instances.
  • get_execution_role() # fails off SageMakerOnly works inside Studio/notebooks. Locally, pass a role ARN string.gotcha
  • # save to /opt/ml/model or the artifact is emptyA job can "succeed" and still produce nothing to deploy if the script wrote the model elsewhere.
  • use_spot_instances=True, max_wait=...Up to ~70% cheaper training — but checkpoint to /opt/ml/checkpoints or an interruption restarts from zero.
  • # wrong image_scopeA training image on an endpoint (or vice-versa) fails at deploy. Match image_scope to the task.
29Studio, JumpStart & the ecosystem

where the SDK sits in the platform

  • # SageMaker StudioThe web IDE. The SDK is the same everywhere; Studio just gives you a role, a kernel and the console alongside.
  • list_jumpstart_models(filter="framework == huggingface")Discover hub models from core.jumpstart.notebook_utils; search_public_hub_models("bert") for free-text.
  • JumpStartConfig(model_id="meta-textgeneration-llama-3-8b-instruct")One config object drives both ModelTrainer.from_jumpstart_config and ModelBuilder.from_jumpstart_config.
  • # MLflow integration model_metadata={"MLFLOW_MODEL_PATH": "models:/m/1"}Train with MLflow tracking and deploy straight from its registry.
  • # EMR Serverless stepRun PySpark inside a pipeline via EMRServerlessStep when preprocessing outgrows a processing job.
  • # v2 still exists sagemaker.readthedocs.io/en/v2Legacy code keeps working on the v2 line; the v3 docs are the default now. Don't mix the two import styles in one script.
1 · The v2 → v3 collapsemany framework classes become two
V2 — ONE CLASS PER FRAMEWORK V3 — ONE CLASS, PERIOD PyTorch TensorFlow HuggingFace SKLearn XGBoost · Estimator ModelTrainer framework = the image PyTorchModel HuggingFaceModel SKLearnModel Model · Predictor ModelBuilder build() · deploy() · invoke() the model is chosen by the container image, not by which Python class you imported
↔ swipe to see the whole diagram
2 · Which package holds whatthe import you reach for, by task
sagemaker.train ModelTrainer SourceCode · Compute InputData distributed (Torchrun) tuner · aws_batch → you TRAIN here sagemaker.serve ModelBuilder InferenceSpec SchemaBuilder ModelServer · Mode optimize() → you DEPLOY here sagemaker.mlops Pipeline · steps ProcessingStep ModelStep · TuningStep feature_store EMRServerlessStep → you AUTOMATE here sagemaker.core — the typed resource layer under all three resources: TrainingJob · Model · Endpoint · TransformJob · ModelPackage · FeatureGroup helper.session_helper: Session · get_execution_role image_uris · parameter · processing · transformer · clarify · lineage · workflow replaces boto3.client("sagemaker") — full API parity, but typed, chained, and defaulted
↔ swipe to see the whole diagram
3 · The container I/O contractthe paths your script must honour
S3 input InputData( channel_name="train") s3://bkt/train the training container /opt/ml/input/data/train ← each channel mounts here SM_HPS · SM_CHANNEL_TRAIN ← env vars from the SDK /opt/ml/model/ → SAVE HERE or the artifact is empty /opt/ml/checkpoints/ ←→ synced to S3 (Spot-safe) S3 output model.tar.gz OutputDataConfig .s3_output_path the same shape applies to processing and inference: processing → /opt/ml/processing/input and /opt/ml/processing/output inference → InferenceSpec.load(model_dir) reads what training wrote to /opt/ml/model
↔ swipe to see the whole diagram
4 · Choosing how to servematch the mode to the traffic
how will it be called? a whole dataset, offline Batch Transform steady real-time traffic real-time endpoint spiky / low volume or idle often Serverless huge payloads or minute-scale latency Async Inference just testing the InferenceSpec IN_PROCESS / LOCAL the cost rule of thumb real-time bills per hour always · serverless bills per request · batch bills only while the job runs
↔ swipe to see the whole diagram
Worth memorising
v3 is a rewrite, not an upgrade
Check sagemaker.__version__ first. Anything below 3.0 is the old Estimator/Model/Predictor SDK — a different API with a different import layout.
ModelTrainer replaces every *Estimator
One class for PyTorch, TensorFlow, HuggingFace, SKLearn, XGBoost and custom containers. The framework is decided by the image, not the class you import.
ModelBuilder replaces every *Model
And build() is now a separate step before deploy(). Pass model=trainer to go from training to endpoint with no glue code.
.train() not .fit(), .invoke() not .predict()
train(input_data_config=[InputData(...)]) takes a list of channels; endpoint.invoke(body=..., content_type=...) takes bytes and returns bytes.
config objects, not loose kwargs
Compute, SourceCode, InputData, StoppingCondition replace instance_type=, entry_point=, TrainingInput, max_run=.
everything lives under sagemaker.core
Session, get_execution_role, image_uris, Transformer, parameter, clarify, lineage, workflow — all moved there, and core.resources.* replaces raw boto3.
serializers / deserializers are gone
Handle encoding yourself with json.dumps / json.loads. You pass a content_type to invoke and decode the response bytes.
the four packages, by verb
train to train, serve to deploy, mlops to automate, core underneath them all. Import explicitly from each; the bare import sagemaker style is gone.
fine-tuning is v3-only
SFTTrainer, DPOTrainer, RLVRTrainer, RLAIFTrainer — LoRA, preference optimisation and RLHF, serverless, with no v2 equivalent at all.
save to /opt/ml/model
Only what the script writes there is tarred into model.tar.gz. A job can succeed and still hand you an empty artifact if you saved elsewhere.
a real-time endpoint bills per hour
Traffic or not, it charges while it exists. Endpoint.get(name).delete() is the single biggest way to avoid a surprise bill; serverless and batch scale to zero.
get_execution_role() only works on SageMaker
Inside Studio and notebooks it resolves the attached role; run it locally and it fails — pass a role ARN string instead.
under a PipelineSession, jobs don't launch
Calling trainer.train() or processor.run() returns step_args for a pipeline step instead of running immediately. That deferral is the whole pipeline trick.
match image_scope to the task
image_uris.retrieve(..., image_scope="training") vs "inference" — the serving image differs, and the wrong one fails at deploy time.