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.

Thanks for the explanation. I removed the accepted-push retries and ran a new test following your suggestions. Unfortunately, the first update still has not been fetched the next morning.

For this test I registered a new Order Type and certificate, with just one synthetic order and one webServiceURL. I removed the previous test orders from the affected iPhone and paused their server workers. The new type had never received a merchant update push before this test. Low Power Mode and Low Data Mode are off, and I have now explicitly checked that Wallet cellular data is enabled. I put Wallet in the background rather than force-quitting it, locked the phone before sending, and have not pulled to refresh or re-added this order.

All times below are Europe/Budapest, UTC+01:00, October 31–November 1, 2026, on the same iPhone 16 Pro / build 24B119.

There was also an initial registration delay:

  • 20:17:24: added the new order on the Mac. It appeared on the iPhone and produced the initial notification within seconds.
  • 20:17:34: the phone requested and received a token for the new Order Type. Just before the token callback, financed scheduled its next Orders activity with Delay=3599 seconds.
  • 21:21:27: that scheduled activity ran (com.apple.financed.orders.tasks: Run (nudge)), registered with our service (HTTP 201), and fetched revision 1 (HTTP 200). The phone logs confirm this sequence. Wallet entered the foreground later, at 21:22:02.

I waited another 71 minutes after registration before the first actual update:

  • 22:32:40: published revision 2, changing the order to a processing shipping fulfillment. updatedAt strictly increased; order ID, authentication token, service URL and createdAt stayed unchanged. Sent exactly one push; APNs returned 200. Body {}, default priority 10, push-type omitted, same production HTTP/2 transport with TLS verification.
  • 22:32:41.281602: financed logged receipt for the new topic.
  • 22:32:41.281973: its Orders handler logged receipt for the new Order Type, followed by an ACK.
  • By 09:14 the next morning, more than 10 hours 40 minutes later, there had been no changed-orders request or package request. The last authenticated response was still revision 1. There was no visible update notification.

No confirmation retries, alternate payloads, header probes or further state changes were sent under this new type. The server still records only that one APNs acceptance.

I retained the immediate post-push phone log archive and collected a fresh full sysdiagnose at 09:06:46 on November 1 while the order was still stalled. The available overnight unified logs, from midnight to 09:07, show no Orders activity/fetch. The powerlog DAS activity-lifecycle table independently records the 21:21 registration activity, but no later execution of com.apple.financed.orders.tasks, although other background activities continued. The diagnostic snapshot shows financed still running, not suspended. I cannot tell from this whether update work was never queued or was held elsewhere; I do not want to mistake that absence for a proven cause.

Could a budget or backoff survive across a newly registered Order Type on the same device, or is there another device-wide limit we should check? Should the first received push in this setup enqueue an Orders task even if the system then delays it? Also, is the roughly one-hour wait for initial registration expected when a new topic token is acquired?

FB25380857 is still the existing report. I have the new sysdiagnose and the earlier receipt archive available for private attachment there; they are not attached to this public post. The full sysdiagnose was captured the next morning, not immediately after the signal, so please let me know if you need a new controlled update with a specific logging profile or a particular state dump immediately afterward. We can reproduce this with synthetic orders without touching customer data.

I've now attached the new diagnostics to FB25380857, along with a detailed timeline, the immediate receipt log excerpt and a before/after scheduler comparison. Both full sysdiagnose archives are in the private report; no device logs are attached here.

I ran one further genuine change on the same isolated test order today, 1 November. All times below are CET (UTC+01:00):

  • 17:05:49: published revision 3 and sent one push; APNs returned 200.
  • 17:05:50.548915: the phone's financed Orders handler logged receipt, followed by its ACK at 17:05:50.599025. The topic/type fields are privacy-redacted in this capture.
  • 17:28:05: still no changed-orders or package request. The last completed download remained the original revision 1 from the previous evening. There was no visible update notification.

This is only the second accepted update signal on the new Order Type, more than 18 hours after the first. The separate type, single order/service, disabled accepted-push retries and checked power/data settings remain unchanged. The normal sender still uses {}, default priority 10 and no push-type override. For this diagnostic run the phone was USB-connected and unlocked, with Wallet reported backgrounded and no manual refresh; the earlier trial used a locked phone.

The new full capture was hardware-triggered at 17:17:44, so 11 minutes 55 seconds after the send, not immediately. I've attached the 17:03:08 pre-signal baseline too. The separate USB archive captured receipt promptly. I want to be clear about that timing limitation.

In both powerlog lifecycle selections, the last executed Orders task is still the initial registration on 31 October at 21:21:27. There is no later Orders execution recorded. This does not tell me what is pending in the queue. The daemon is alive, not suspended in the snapshot, and handles other events.

Could you look at the private captures and advise which profile or queue/admission-state dump would help distinguish throttling from a missing enqueue/reschedule after receipt? We can run another specific reproduction if needed. I haven't reset the phone, re-added the order or sent more retries.

Thanks - although there is rate limiting, it does appear in this case your device might be hitting an issue.

One quick test would help - restart your iPhone, unlock it, wait a minute, then publish a single update and see if it was fetched. Just a yes/no is fine.

A small request for future updates: short notes with the key times and what happened work best, long generated write-ups can mask important details and the sysdiagnose has all the detail we need. Thanks again for the sysdiagnose. If you let us know here whether restarting fixed the issue, and we'll follow up with you on the feedback ticket.

No fetch in the first two minutes after this restart test. I restarted the iPhone, unlocked it, waited over a minute and left Wallet unopened. Sent one genuine update at 22:23:20 CET (APNs 200); by 22:25:26 there was no list/package request and no visible notification.

One correction to the earlier timeline: revision 3 was fetched at 19:06:31. I now recall also restarting the phone around 19:00, so that earlier fetch may have followed a restart; I don't have the exact reboot time.

Update: state 4 was eventually fetched on 2 November at 14:19:48 CET, 15h 56m 28s after the 1 November 22:23:20 signal. The notification followed at 14:19:49, without another merchant push, manual refresh or Wallet opening before it.

The arrival logs show financed initializing with a different PID but the same boot UUID as yesterday; I don't know why it relaunched. I've retained the arrival log archive if useful.