yes agreed, given there isn’t a feasible solution here yet, the migration deadline should be put on hold.
Yes, I agree with @npiasecki ; postponing till April 2027 seems feasible. We will get a better idea about all scenarios till then.
Hi,
Is there any update here?
Given the issue reported by @farid is also still ongoing, postponing till April 2027 would be great so Shopify has more time to fix any issues and we can be absolutely sure the migration will go smoothly for every partner.
Regarding point #1: You don’t need to refresh all tokens every hour.
The way I’ve implemented it is to make the function that loads the offline session check if it’s expiring soon, and if so, refresh and store it, and return the new one instead.
For long running tasks that reuse the same token, I’ve also implemented an error handler that retries any 401 errors with a new refreshed token.
You DO have to run a background job that checks if any refresh tokens are expiring soon and refresh them proactively (refresh tokens expires after 90 days, so subtract like 7 days in case there are issues refreshing).
However I am concerned about race conditions if the token is refreshed twice at the same time. I see it’s happened a couple times in the logs and no issues seem to have occurred, but race conditions are tricky.
Example scenario:
Refresh 1 gets token A with refresh token A
Refresh 2 gets token B with refresh token B (slightly after refresh 1)
What happens if A gets stored after B, even though on Shopify’s side, B happened after and thus A was invalidated? Shopify sees B as the latest, but we have A. So we lose B and thus cannot refresh the offline session any more?
Update – Here’s some info I found in the docs:
Shopify returns the same refreshed token response for up to 1 hour after the original refresh, so a refresh interrupted by a transient outage can be safely retried once connectivity is restored. After this window, the previous
refresh_tokenis invalid and can’t be used again. Treat network errors, timeouts,5xx, and429responses as transient and keep retrying with the samerefresh_token. The refresh token is only definitively invalid when Shopify returns401witherror: "invalid_request"and the descriptionThis request requires an active refresh_token(or once the refresh token reaches its 90-day expiry); in that case, re-acquire a token through token exchange the next time a merchant opens the app.
In our case we make graphql calls for webhooks received and carrier service calls. For some merchants we can receive thousands of these requests every second. Whilst we do have effective caching in place, there will be times where we need to reach out to Shopify to pull or refresh data and as we receive thousands of requests, particularly with carrier service, we don’t want to delay these, so an up to date access token that is always on hand is critical, as we have a high volume of requests, it’s much more efficient to check once per hour rather than with every request coming in.
The latest update from Shopify where the refresh token remains valid for 1 hour is a good compromise and i think this should alleviate the issues, I will continue monitoring our token refresh script for the next few weeks and see how that goes.
However @Liam-Shopify what happens on the odd chance shopify goes down for more than an hour? Will the refresh token continue to work when it comes back up?
One hour isn’t realistic @Liam-Shopify @Darius-Shopify
As we approach the deadline I become increasinly worried about this transition.
It seems there’s no safe way to guarantee offline tokens, and this will greatly impact all apps usability.
would it be possible for shopify to send the current refresh token with every webhook and carrier service request in the header? it can be encrypted with the same way has HMACs are encoded, this way should there be extended failures, we can ensure recovery is guaranteed with backend processes.
or, send the ID token so we can do a token exchange.
You don’t have to make a request to check if the token is expired. The expiration will be included with the session information, so you just check if it’s expiring soon before using it.
Thank you for fixing the idempotency of the token refresh flow for an hour. This is more resilient than what I believe was the previous implementation.
Still, I encourage Shopify to strongly consider delaying enforcement until April 1st, 2027, as many businesses institute a code freeze during Q4 except for critical breakfix scenarios, and so a January 1st deadline is functionally equivalent to an October 1st deadline or earlier.
In other words, many developers are just now realizing that significant changes may be required within mission-critical fulfillment workflows on a compressed timeline.
I do not mean to be disrespectful: Shopify’s outage last Cyber Monday is still quite fresh in the minds of us who work in warehouses during the holiday season, and our concerns about what exactly would happen with refresh and access tokens during a similar outage ought to be addressed, as it has a potential to make any similar outage for clients significantly more painful.
I would like to highlight that the Cyber Monday outage exceeded an hour in duration and specifically involved a defect involving key rotation in Shopify’s authentication service, so there is a legitimacy to developers viewing this change as an operational risk that merits discussion.
Of course, the move toward expiring and rotating tokens is consistent with broader security practices across the industry. Reading these forums, the security objective is not really in dispute. Instead, many of us are concerned with being able to deliver a stable product through a stressful season over a relatively short timeline.
I think it is fair to say that many of our mutual Shopify clients will not appreciate this nuance of security when things stop working during such a critical period. We all want to do a good job and for our clients to be successful, and the potential scenarios keep some of us up at night.
Thank you for continuing to listen to the community.