Skip to content

Public apps need expiring offline tokens by January 2027

A quiet changelog entry sets a hard date for every public app still holding a permanent offline access token. The work is small; the failure mode is not.

UpdateJune 19, 20263 min read

On 20 May 2026 Shopify published a changelog entry that will matter more than its length suggests: from 1 January 2027, all public apps must use expiring offline access tokens. Apps still holding permanent ones will not keep working past that date, and that includes apps created long before the rule was written.

What is actually changing

An offline access token is the credential an app uses when nobody is logged in — the one behind webhook processing, scheduled jobs, background syncs and every piece of an app that runs while the merchant is asleep. Historically those tokens did not expire. Once granted, they were good until the app was uninstalled.

Under the new rule they expire, and the app is responsible for refreshing them. That is the whole change, and the reason is the ordinary one: a credential that never expires is a credential that never gets rotated, and a leaked one stays useful indefinitely.

Scroll the figure sideways to see all of it

What it means for an app you already ship

The important detail is who does the work. Merchants do not reinstall. There is no consent screen, no email campaign, no support queue full of people asking why they were logged out. The migration happens on the developer's side: exchange the credential, store the new one along with its expiry, and refresh before it lapses.

Concretely, that means three things in the app itself.

  • Storage changes shape. A row that held one string now holds a token, an expiry, and whatever is needed to obtain the next one. Anywhere in the codebase that reads "the token" now has to read "a currently valid token".
  • Refresh has to be centralised. If token reads are scattered across a dozen call sites, this migration is where that gets fixed, because the alternative is a dozen places that each need to know about expiry.
  • Failure has to be handled. A refresh can fail for reasons that are not transient — an uninstalled app, a closed shop, a revoked grant — and those need a different response from a network blip. Shopify documents a retry window; use it for the transient case and stop for the rest.

Why it is easy to miss

This deprecation has none of the signals that make a deadline visible. It does not break a page a merchant looks at, and it is not the kind of change that surfaces where anyone is already looking. It fails at a date, in the background, on the part of the app nobody demos.

It is also the kind of work that gets deferred because it is invisible when done. Nothing about the app looks different afterwards, which makes it hard to schedule against features and easy to move to the next sprint, repeatedly, until December.

What we would do now

Find out whether it applies. If the app is public and stores an offline token that has no expiry column next to it, it applies.

Then treat it as a data migration rather than an auth change, because that is where the risk actually is. The credential exchange is a documented flow. The part that goes wrong is a token store that was written five years ago by someone who assumed a string was enough, read from places that predate the current architecture, in an app that cannot be taken offline while it is fixed.

From this announcement to the deadline is a little over seven months, which is comfortable. Starting in December is not.

One more thing worth doing while you are in there: log refresh failures with the shop domain and the reason. When something does go wrong in January, the difference between an afternoon and a week is whether you can tell which shops are affected without querying every row.

If you maintain a listing, this sits with the rest of public app work; if the app is custom or private, the same storage question still applies to private apps.

Blog