The situation
A subscription team runs three LLM features on Amazon Bedrock: a ticket classifier, a reply drafter, and a data-extraction job that turns free-text emails into records. All three call one foundation model, named by an explicit version id in a config file set about eighteen months ago. It has been reliable ever since, which is why nobody has touched it.
Then a notice lands. The model version they depend on is moving to Legacy, with an end-of-life date about six months out. After that date the model is removed from every Region and calls to it fail. A newer version of the same family is available, along with a couple of newer families, but none is a drop-in guarantee. The extraction job is sensitive to output format, and one of the three features runs on a fine-tuned model with a Provisioned ThroughputReserved Bedrock capacity bought by the hour for a fixed term, paid for whether traffic fills it or not. commitment attached.
The team has two bad instincts to resist. One is to wait until the deadline forces a panicked swap. The other is to flip everything to the newest model this afternoon. Neither is a plan. What they need is a way off a retiring version without breaking production, and an application shape that makes the next deprecation routine.
What actually matters
Model versions are a stability contract, and deprecation is that contract expiring. Pinning an explicit version id is the right default, because the model behind a feature then does not change between deployments. What comes with it is a migration on AWS’s calendar rather than yours. The opposite posture is to chase the newest model in a family. Bedrock gives you no help with it. Every foundation model id names a version, and AWS publishes no floating alias that resolves to the latest one, so chasing means your own code or your own dependency bump picks a new id up. The scheduled migration goes away, and behaviour change arrives whenever your resolution does. A prompt that worked yesterday starts formatting its answer differently, nothing errors, and you find out from a downstream parser or a customer.
The lifecycle has more structure than that, and the details change what a runway is worth. Bedrock reports a model as ACTIVE or LEGACY in the modelLifecycle field of GetFoundationModel, alongside legacyTime, publicExtendedAccessTime and endOfLifeTime. Models launched before 7 September 2026 sit in Legacy for at least six months. For models launched on or after that date, the model card names the legacy period, and it is either six months or 45 days, with six the usual one. Read the card before you pin. Forty-five days is not a quarter of planning.
Four Legacy restrictions land on a migration in progress. New Provisioned Throughput cannot be created for a Legacy model, and new fine-tuning jobs cannot be started against it. For a model launched before 7 September 2026 whose end-of-life date falls after 1 February 2026, a minimum of three months in Legacy is followed by public extended access, at a price the provider sets. Bedrock’s pricing page carries those rates in a table of their own: Claude 3.5 Sonnet’s is USD$6.00 per million input tokens and USD$30.00 per million output tokens from 1 December 2025. AWS documents no equivalent period for models launched on or after that date. And an account that has not called a Legacy model for 15 days can lose access to it, so a rollback nobody exercises may not be there when it is reached for.
The second concern is how tightly the application is wired to one model’s request shape. Hand-built payloads against a specific model mean that changing the model id means rewriting request construction, and that friction turns a migration into a project. Converse gives one request and response shape across every Bedrock model that supports messages, covering tool use and guardrails, with ConverseStream for streaming. Model-specific inference parameters still go through a per-model structure, and two models still answer the same prompt differently. What disappears is the mechanical rewrite.
The third is proving the successor behaves before you trust it. A model swap is a behaviour change even within one family, and the honest check is a saved Golden datasetA versioned set of representative inputs with known-good expected outputs, run on every prompt or model change to catch regressions. scored against both. Bedrock evaluations run programmatic jobs on your own prompt dataset, and judge-model jobs where a second LLM scores each response and explains the score. Those jobs accept foundation models, customised models, imported models and Provisioned Throughput models as targets. A home-grown replay harness does the same work. What matters is that the comparison runs before cutover.
The fourth is the cutover mechanism. A candidate that passes the eval set can still behave differently under live traffic, so the change has to be reversible in seconds rather than redeployed over minutes. A config value or feature flag selecting the model id, rolled out to a slice of traffic first, turns a bad successor into a flag flip. The rollback only exists while the old version is still invokable, which is a second reason to start well before the end-of-life date.
The fifth cuts across the others. Prompts and few-shot examples are tuned to one model, not universal. A successor may need the instruction reworded, the examples swapped, or the output contract restated. Plan that retuning into the migration rather than assuming the prompt library travels unchanged.
Custom models are the heavier case, and the two kinds differ. A model fine-tuned on Bedrock is trained against a specific base version, so a deprecated base can mean re-tuning against the successor base rather than repointing an id. Serving it usually means Provisioned Throughput, sold in Model unitThe billing block Provisioned Throughput is sold in – one unit delivers a fixed tokens-per-minute rate for a specific model. by the hour, with an optional one- or six-month term at a lower rate. On-demand serving for a customised model exists as a custom model deployment, but only in us-east-1 and us-west-2, only on a short list of base models, and only for models customised on or after 16 July 2025. Custom Model Import works differently again: your own weights from S3, served on demand, with no Bedrock base version underneath to deprecate.
What we’ll filter on
- Behaviour stability, does the feature need identical output over time, or can it absorb drift?
- Migration lead time, how long is the legacy period on the model card, and how much work is the move?
- Request-shape coupling, how tightly is the app wired to one model’s native payload?
- Regression detection, can we score the successor before it takes traffic?
- Cutover and rollback safety, can we switch, canary, and revert without a redeploy?
- Custom-model weight, is a fine-tuned or imported model in the path, and what serves it?
The landscape
Explicit version pinning. Bedrock model ids carry a version suffix, in the shape anthropic.claude-sonnet-4-20250514-v1:0, an id that is itself Legacy now with an October 2026 end-of-life date. Pinning one keeps a feature calling exactly that model until you change it, which is why production behaviour holds steady between deploys. The trade is a scheduled migration you own.
Chasing the newest version. Reaching for the latest model in a family avoids the forced migration and moves the behaviour change to whenever your own resolution of “latest” moves. Quality often improves. Format, tone and edge-case handling can shift with no error raised. Reasonable for human-read features, risky for anything a machine parses.
Model lifecycle status. AWS documents three states, Active, Legacy and end-of-life, with the API reporting the first two as ACTIVE and LEGACY; after the end-of-life date the model is gone from every Region. AWS says it notifies you of the end-of-life date at the start of the Legacy period, without naming the channel, and publishes the status itself in the Bedrock console and in the API. The model card carries an “EOL no sooner than” date and the length of the legacy period; the API carries the exact timestamps once they are set.
Inference profileA Bedrock resource wrapping a model so calls to it can be tagged, routed across regions, or repointed without changing app code.. Many calls go through a cross-Region inference profile rather than a bare model id. A profile defines a model and the Regions requests can route to, so it inherits that model’s lifecycle. Profiles do not support Provisioned Throughput, so a fine-tuned deployment is called directly instead.
The Converse API. One request and response shape across models that support messages, so the model id becomes a parameter. It removes the mechanical work of switching and none of the behavioural risk, which is why an eval set still matters. Per-model Invoke payloads tie each feature to one model’s quirks and make every migration a rewrite.
Bedrock evaluations. A regression check against a saved dataset turns a swap into a decision. Programmatic jobs score a candidate on your own prompt dataset. Judge-model jobs have a second LLM score and explain each response, and human evaluation jobs bring reviewers in. A custom replay harness does the same work for teams that already hold golden data.
Custom and fine-tuned models. A fine-tuned model is bound to the base version it was trained on. Once that base goes Legacy you cannot start new fine-tuning jobs against it or create new Provisioned Throughput for it. Existing throughput and existing on-demand deployments keep working. AWS also still lets you create a new custom model deployment for on-demand inference, as long as the customisation predates the base going Legacy. An imported model is your own weights and carries no base version at all.
Evaluation
Side by side
| Option | Stable output | Notice needed | Low coupling | Scores the successor | Instant rollback | Cost shape |
|---|---|---|---|---|---|---|
| Pin explicit version | ✓ | Legacy period | ✗ | ✗ | ✗ | On-demand tokens |
| Chase the newest | ✗ | None | ✗ | ✗ | ✗ | On-demand tokens |
| Converse for the call | n/a | n/a | ✓ | ✗ | ✗ | No charge of its own |
| Saved eval set | n/a | n/a | ✗ | ✓ | ✗ | Evaluation job |
| Flagged canary cutover | n/a | n/a | ✗ | ✗ | ✓ | Negligible |
| Fine-tuned on Provisioned Throughput | ✓ | Re-tune, so longer | ✗ | ✗ | Dual-run only | Hourly per model unit |
The bottom five rows compose with each other rather than competing. Reading the table against the three features: the classifier and drafter want a pinned version reached through Converse, an eval set, and a flag-controlled cutover. The fine-tuned extraction path wants all of that plus a re-tune against the successor base and a planned overlap of old and new Provisioned Throughput. Chasing the newest model is off the table for extraction the moment a parser depends on its output shape.
The solution
Five steps, and the order matters. Pin an explicit version in config rather than inline, so the id is one value to change and roll out like any other setting. Monitor for the notice rather than waiting on it. AWS does not say where the Legacy announcement lands, so read the status yourself: a scheduled GetFoundationModel call that reads modelLifecycle and alerts on LEGACY catches the case where the announcement reached an address nobody opens. Test the successor against the saved eval set on the same inputs as the incumbent, treating a format change or a quality drop as a blocker to investigate. Cut over behind a flag, to a canary slice first, watching quality and error signals before widening. Keep a rollback by leaving the old version invokable until the successor has held on real traffic.
That last step needs care, because a Legacy model can be withdrawn from an account after 15 days without a call. Send it a small, regular slice of traffic, or a synthetic call on a schedule, for as long as you want the option. Watch the rate too. Three months into the legacy period a model under the pre-September-2026 policy can enter public extended access, at the price the provider sets.
Two details ride alongside the five steps. Prompts and few-shot examples are tuned to the incumbent, so expect to retune for the successor, and the eval set is what tells you whether the old prompt still holds. And Converse is what keeps the id swap from becoming a rewrite: if the app already speaks Converse, changing the model behind a feature is a config change plus a validation pass, not a change to request construction.
The fine-tuned model deserves its own timeline. It is trained against a specific base version, so a deprecated base can mean a re-tune: a training job to schedule, a new artefact to evaluate, and new serving capacity to stand up. Start that the day the notice lands. Once the base is Legacy you cannot launch a new fine-tuning job against it, and you cannot create new Provisioned Throughput for it either. Existing throughput keeps running, so plan an overlap where the old commitment and the new one both exist, evaluate and canary the re-tuned model, then delete the old Provisioned Throughput. Billing runs until you delete it, and a committed term cannot be deleted early.
Worked example
The classifier calls a model through a version id in a config value, over Converse, and has run untouched for eighteen months. A notice marks that version Legacy with an end-of-life date six months out and names a successor in the same family.
Day one, not month five. The team already holds a saved eval set for the classifier: a few hundred tickets with known-correct labels, taken from real traffic and frozen. They run the successor against it through Converse, changing only the model id, and compare label for label with the incumbent. The successor agrees on 97 per cent of the set and flips a cluster of billing-versus-account edge cases, labelling an ambiguous phrase the other way. That is a regression to fix, not to wave through. They sharpen the label definitions in the prompt, add two examples covering those cases, re-run the eval, and the disagreement clears.
Cutover is a flag. Five per cent of traffic goes to the new model id. They watch the classifier’s confidence scores and the downstream correction rate for a few days, widen to twenty-five per cent, then to everything. The old version stays pinned and reachable throughout, kept warm by a scheduled synthetic call so the 15-day inactivity rule does not withdraw it. At any point a bad signal is a flag flip back to a known-good model. Once the successor has held on full traffic, they drop the old version from config, well ahead of the end-of-life date. Total code change: a config value and two prompt examples.
What’s worth remembering
- Check
modelLifecyclefor status. A model isACTIVEorLEGACY, withlegacyTime,publicExtendedAccessTimeandendOfLifeTime; calls fail after the last. - Read the model card’s legacy period. At least six months for models launched before 7 September 2026; on or after, six months or 45 days.
- Legacy blocks new work. You cannot start new fine-tuning jobs on a Legacy model or create new Provisioned Throughput for it.
- Keep the rollback warm. An account that has not called a Legacy model for 15 days can lose access to it.
- Score the swap, flag the cutover. Converse removes the rewrite, a saved eval set scores the successor, a flagged canary makes rollback a flip.
- Fine-tuned models inherit deprecation. They are bound to a base version and usually served by Provisioned Throughput; an imported model has no base version.