Wallet Orders updates arrive hours late even though the push reaches the device

I'm implementing Wallet order tracking for a shop and have run into an update problem that I haven't been able to explain. This is the Wallet Orders web service and signed .order packages, not .pkpass passes or orders found in Mail.

I've filed FB25380857 with a detailed timeline and a redacted sender example. I'm posting here because I would also like someone to check whether there's a mistake or unsupported assumption in our integration. If there is a parameter or response we should change, I'd much rather find it now than blame the OS.

The short version: the phone receives our APNs message almost immediately, but sometimes doesn't ask our server for the updated order for hours. Once it finally makes the request, the package downloads, applies and produces the expected notification normally.

How the service is set up

Orders are added from Safari using the Wallet button. There is no separate native app. Registration succeeds, and the phone initially downloads and displays the order.

We send to the production APNs endpoint over HTTP/2, using the Order Type certificate and key. The topic matches the Order Type ID. The request body is exactly {}. Our normal sender leaves the priority at its default of 10, and for the tests below I explicitly set it to 10. The push-type header is omitted. TLS verification is enabled, and apns-expiration is set to the current time plus one hour.

The effective request is:

POST https://api.push.apple.com/3/device/<registeredPushToken>
apns-topic: <orderTypeIdentifier>
apns-priority: 10
apns-expiration: <currentEpochPlus3600>
content-type: application/json

{}

Each update keeps the same order ID, authentication token, webServiceURL and createdAt. updatedAt is an RFC 3339 timestamp and strictly increases. The device registration endpoint returns 201/200. The changed-orders endpoint returns lastModified and the registered orderIdentifiers, or 204 if nothing has changed. The package endpoint returns the signed .order with the finance.order MIME type, Last-Modified and conditional 304 support. The changed-orders response is no-store, and the package response is private, max-age=0, must-revalidate.

One detail I'm unsure about: our isolated test orders share one Order Type ID, but each test has its own stable webServiceURL. Is that supported, or should all orders under an Order Type use the same service URL?

The affected phone's diagnostic build is 24B119, listed in Feedback Assistant as iOS 27.2. The Wallet logging profile was already installed before these tests, and the phone had been restarted. These are synthetic orders, with no real purchase or carrier operation.

The longest delay we captured

Times below are local, Europe/Budapest, UTC+01:00, on October 30–31, 2026.

  • October 30, 18:43:56: the screen is off.
  • 18:44:16: we change the order from ready for pickup to picked up/completed and send the update signal. APNs returns 200.
  • 18:44:16.903: apsd receives the message. At .905, financed logs receipt in both its Push and Orders handlers for our exact Order Type.
  • No immediate Orders task or changed-orders request follows. Normal confirmation retries go out at 18:55:02 and 19:05:02.
  • October 31, 10:53:22–23: Wallet enters the foreground and becomes active.
  • 10:53:25.884: pending Orders work starts.
  • 10:53:26: the phone asks for changed orders and downloads the pending package with HTTP 200.
  • 10:53:27: the phone logs that it applies the update and schedules the notification. The picked-up notification appears.

That is 16 hours, 9 minutes from the first signal to the package response. There was no new signal from our server that morning. I had opened Wallet, but did not deliberately pull to refresh; I can't completely rule out an accidental gesture. I therefore don't want to claim that opening Wallet alone is a reliable workaround.

We have also captured a shipping update that took about 41 minutes, and another completion update that took almost two hours despite the phone being locked before the send. In that second case, the logs show a previously scheduled Orders task running just before the successful fetch, rather than a new push arriving then. An explicit manual pull can fetch the same pending package promptly.

For comparison, a new order on another iPhone made its changed-orders request and downloaded an update within three seconds. We have not yet confirmed the visible result on that phone, and it was only a processing-description change, so it isn't an equivalent fulfillment-notification test.

We tried explicit priority 10, an alert push-type control, and one background/priority-5 control. They did not produce an immediate fetch in the captured windows. A separate content-available payload experiment also reached the handler without starting a fetch; that is not our normal payload and hasn't been deployed as a fix. The full report keeps these controls and normal retries separate.

What I'd like to understand
  1. Is the APNs request above correct for Wallet Orders? Are we missing a required header, payload detail or registration step?
  2. Could the shared Order Type with different webServiceURLs cause this, even though the same order updates successfully after a manual pull or later task?
  3. Is there a supported way to recover when a received update signal leaves the changed-orders request pending for hours? What conditions should we check before sending more signals or asking users to re-add an order?
  4. What further diagnostic would be useful? We have retained the original phone's sysdiagnose and separate log archives for these events and can provide them privately through the Feedback report.

A 15–30 minute delay would be acceptable for our parcel-status use case. An order still showing ready for pickup the next morning is a different problem. I'm not suggesting Apple promises a particular delivery time; I'm trying to find out whether we can make this integration reasonably dependable, and what we need to correct on our side.

No keys, device/push tokens, customer information or full device logs are included in this post.

Thanks for the detailed report. Your APNs request looks correct. For Wallet Orders, the payload is ignored, and apns-priority and apns-push-type don't change how the update is handled. A push only tells Wallet that something changed for that Order Type, and Wallet then decides when to ask your web service for the list of changed orders.

That request is rate-limited per Order Type on each device. Once the limit is reached, the work is deferred and the system runs it opportunistically, which can take much longer when the phone is locked and idle. Your test setup is likely hitting this limit:

  • All your test orders share one Order Type.
  • Your server re-sends the push about every 10 minutes after APNs has accepted it.
  • Each control push (priority 5, alert, content-available) adds to the same per-device budget.

That would explain why your second iPhone, with a fresh order and no history of test pushes, fetched within seconds.

Using one Order Type with several stable webServiceURLs is supported. However, each update makes Wallet query every web service registered under that Order Type. Test services that have been retired, or that return errors, add retried work, so it's worth removing them.

I'd suggest the following:

  • Send a single push for each real change to an order, and don't resend pushes that APNs accepted with a 200.
  • Use a separate Order Type for testing, and keep the number of active test web services small.
  • Leave time between test bursts on the same device.

Low Data Mode, cellular data turned off for Wallet, or lower power mode can also delay background updates, so please check those settings on the affected phone. Re-adding the order shouldn't be needed.

If you still see multi-hour delays after making these changes, please attach a sysdiagnose captured right after a push that wasn't followed by a fetch to FB25380857, making sure to note the time you sent the push so we can match it up in the logs.