Skip to content

Claude's Dated Model Snapshots and Why the -latest Alias Moves

8 min read · updated August 11, 2026

The model field in a Claude request can name a specific set of weights or a moving pointer to whatever is newest in a family. Both are strings, they look almost the same, and only one of them still means the same thing next quarter.

How the id is built

Anthropic’s model ids are built from a family, a version and a release date, in that order:

claude-sonnet-4-5-20250929
       ------- --- --------
       family  ver  snapshot date (YYYYMMDD)

claude-3-5-sonnet-20241022     older ordering, same three parts
claude-opus-4-1-20250805

The trailing eight digits are the important part. They identify one immutable snapshot: a specific checkpoint, with specific behaviour, that does not change after the date it was published. Two calls to the same dated id a year apart hit the same weights.

Alongside those, Anthropic publishes aliases — the family and version without a date, and on some platforms an explicit -latest suffix. An alias resolves, at request time, to whichever snapshot Anthropic currently designates as the one for that family. When a new snapshot ships, the alias points at it. Your code did not change. Your deployment did not change. The model did.

Model ids and alias availability differ by platform. Ids used here are illustrative of the naming convention; the current list is on Anthropic’s models overview. Notably, the managed cloud platforms that resell Claude have historically required fully qualified versions and not accepted the bare aliases at all.

What moving means in practice

The change is not usually a regression. A newer snapshot is generally better on aggregate. That is precisely what makes it awkward: the things that break are not the things the release notes talk about.

  • Prompts that were tuned against a specific failure mode. You added three sentences to a system prompt because the model kept wrapping JSON in a code fence. The new snapshot does not do that, and your three sentences now push it toward something else.
  • Output length and format drift. Downstream regexes, markdown parsers and fixed-width UI all assume a shape. Verbosity is one of the properties that most reliably shifts between snapshots.
  • Cost and latency. A newer snapshot can be more willing to use tools, or to produce longer answers, and your per-request cost moves without a price change.
  • Evaluation baselines stop meaning anything. A score recorded in March against an alias cannot be compared with a score recorded in September against the same alias. You have two numbers from two models with one label.
  • Prompt cache invalidation. A cached prefix is keyed to the model serving it. When the alias moves, the cache behind it does not carry over.

None of these produce an error. That is the whole problem: the request succeeds, the response is plausible, and the regression shows up as a slow drift in a quality metric that nobody attributes to a model change because nobody made one.

What pinning does not pin

It is worth being precise about the guarantee, because pinning is sometimes oversold as reproducibility. A dated snapshot fixes the weights. It does not fix the sampler’s non-determinism on shared hardware, and it does not fix anything the provider operates around the model — request-time safety systems, serving-stack changes, or the infrastructure-level numerics that make two identical requests at temperature 0 occasionally diverge. Pinning removes one large source of variance, the one you would otherwise never see coming, and leaves the smaller ones in place.

The practical translation: a pinned model makes an evaluation comparable over time, and it does not make an output reproducible. Do not write a test that asserts on an exact response string and expect pinning to keep it green.

Two requests, side by side

The difference is eight characters. Here is a pinned request:

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5-20250929",
    "max_tokens": 1024,
    "system": "Reply with a single sentence.",
    "messages": [
      {"role": "user", "content": "Summarise the attached ticket."}
    ]
  }'

and the same request riding the alias:

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "system": "Reply with a single sentence.",
    "messages": [
      {"role": "user", "content": "Summarise the attached ticket."}
    ]
  }'

The second is the right call in a notebook, in a one-off script, in a documentation example that should not go stale. It is the wrong call in anything whose output somebody depends on, and it is the wrong call in any test that is supposed to detect regressions, because it cannot distinguish your regression from Anthropic’s improvement.

The interesting case is the one in between: a batch job, a scheduled report, an internal tool. These are usually written with an alias because nobody wants to maintain a version number for something that runs once a week, and they are also the jobs least likely to have a human reading the output closely. A pinned id and an annual review is less work in total than debugging a report that started summarising differently in March, because the second of those begins with not knowing that anything changed.

The field that tells you what answered

Every Messages API response echoes the resolved model id, and this is the part most integrations never persist:

{
  "id": "msg_01XFDUDYJgAACzvnptvVoYEL",
  "type": "message",
  "role": "assistant",
  "model": "claude-sonnet-4-5-20250929",
  "content": [{"type": "text", "text": "..."}],
  "stop_reason": "end_turn",
  "usage": {"input_tokens": 417, "output_tokens": 61}
}

Send the alias and the response still names the dated snapshot. That field is the audit trail: log it next to every generation you store, alongside usage, and a quality drift six weeks later becomes a five-minute query rather than an argument. Without it you have a collection of outputs that you cannot attribute to anything.

It is also how you find out that the alias moved, which is otherwise not announced to your application in any way at all.

There is a second, subtler use for the field even when you are already pinned. Requests do not always go where you think: a retry wrapper with a hard-coded fallback, a feature flag, a shared library with its own default, a staging configuration that leaked into a batch job. The returned model is ground truth about what served the request, and comparing it against the id you intended is a two-line assertion that catches an entire category of configuration drift. Log both, and the day somebody asks why last Tuesday’s outputs look different, the answer is in a column rather than in a reconstruction.

A pinning policy that survives contact

  1. Pin in every environment that matters. Production, staging and the evaluation harness all name a dated snapshot. Aliases are for scratch work.
  2. Keep the id in configuration, not in code. One environment variable, read in one place. Upgrading a model should be a config change you can roll back, not a deploy.
  3. Log the returned model field with every stored generation, and alert if it is ever a value you did not configure.
  4. Run the new snapshot alongside the old one before switching. Same eval set, same prompts, both pinned, and look at output length and tool-call rate as well as accuracy.
  5. Set a calendar reminder against the deprecation page, because pinning is the thing that eventually breaks loudly: a pinned id is retired on a schedule, and an alias never is. That trade-off, and the notice you are owed, is on the deprecation policy page.