Media, Publishing & Streaming// diagnostic

The app says subscribed, the site says not

In short

Get the internal subject identifier from both surfaces before investigating anything else, because most of these reports turn out to be two separate accounts rather than one account out of sync. If the identifiers match, the remaining causes are that each surface resolves entitlement from a different authority, or that one of them is holding a decision minted before the entitlement changed.

Key takeaways

  • Ask for the subject id on each surface first — 2 accounts is the most common answer by a wide margin.
  • A store receipt identifies a purchase, not a person, so an in-app subscriber has no web identity until one is created.
  • Institutional access matched on IP range works on the office network and fails on mobile data, which reads as an app bug.
  • A token minted before an entitlement changed keeps answering the old question until it expires.
  • Email is not an identifier: relay addresses and address changes break every join built on it.

Three causes produce this ticket and they are separated by one question asked at the start: what internal subject identifier does each surface think it is looking at? Either the identifiers differ, in which case there are two accounts and no synchronisation problem at all; or they match and each surface is asking a different authority about the same person; or they match, both ask the same authority, and one is holding an answer it obtained before the entitlement changed. Everything else is a variation on these three, and the first is the most common by a wide margin.

If both surfaces are wrong for the same reader, this is not the page — the grant itself probably never changed, which is renewals that never reached the access system. If the website is inconsistent with itself between requests, that is a cache-key problem traced in subscribers hitting the wall on popular stories.

Both identifiers, before any theory

  1. Get the internal subject id from the app. Not the email, not the store receipt — the identifier your own systems key entitlements on. Put it in a debug screen so support can read it aloud rather than guessing.
  2. Get the same id from the website, from an equivalent account screen or a diagnostic endpoint. If the two strings differ, stop: you have 2 accounts, and the rest of this page is irrelevant.
  3. Record which authority each surface consulted and when, with the instant of the answer. A surface that cannot say where its answer came from is the surface to fix first.
  4. Record the age of the credential on each side: when the token or session was issued, and when it expires. This one field resolves the third cause without further work.
  5. Ask what network the reader was on. Institutional access resolved by IP range is present on the office wifi and absent on mobile data, and the reader will describe that as the app being broken.

Two accounts wearing one reader's name

A purchase made inside an app arrives as a receipt from a store — Apple's or Google's. That receipt says a transaction happened for a subscription product on a device; it does not tell the publisher who the person is, and in most flows it never will unless the reader is asked to create or connect an account. So the app can be entirely correct that a subscription exists, and the website entirely correct that the person in front of it has none, because they are not the same record.

  • One reader, two signup routes. Bought in the app on Sunday, signed up on the website with a work address on Monday, and neither knows about the other.
  • One reader, two providers. Signed in with a social or platform identity on one surface and an email password on the other, producing two subjects with no link between them.
  • One household, two people. The subscription is genuinely on somebody else's account, and the reader in front of you never had access to begin with.
  • One reader, an old account they have forgotten. The disagreement is real and the fix is a merge, not a sync. How to connect a store purchase to a web account is its own guide — linking store purchases to the web account.

This class is worth naming in your support tooling rather than in an engineer's head. A single screen that takes an email or a receipt and shows every subject associated with it, with the source of each, turns a 2-day investigation into a 30-second answer, and it is the kind of internal surface that repays its build cost in the first month.

The same reader, asking different systems the same question

The second cause is architectural. Each surface was built at a different time by a different team against whatever access source existed then, so each resolves entitlement its own way and they agree only by coincidence.

SurfaceWhat it typically asksHow it goes wrong
Native appThe store receipt on the device, validated at launchA receipt is per store account, and cannot see a web-side cancellation or refund
WebsiteA session flag written at login from the billing recordNever refreshed within the session, so a renewal mid-session is invisible
Newsletter toolA marketing tag synced nightlyUp to 24 hours stale, and silently wrong whenever the sync fails
Institutional accessAn IP range or an email domain matchPresent on the office network, absent on mobile data and at home
The same subscriber, 4 surfaces, 4 sources of truth

The institutional row is the one that produces the most confusing tickets, because the reader's access appears and disappears with their location and they have no reason to connect the two. If a seat, a domain match or an address range is involved, read the behaviour described in seats, domains and IP ranges for institutional access before treating it as a synchronisation defect.

There is a second trap in the website row. When the site fails to recognise a subscriber it usually does not lock them out immediately — it falls back to the meter, so they read 3 or 4 stories and only then hit a wall. That delay makes the report arrive detached from its cause, and it is why the meter's own behaviour, described in the meter resets in a private window, keeps turning up inside entitlement investigations.

Four systems each holding a defensible opinion about who is a subscriber is not a synchronisation problem. It is three systems too many.

Right answer, wrong moment: credentials that outlive the change

The third cause is timing. A token issued at login carries claims that were true when it was minted, and a native app holds that token far longer than a browser tab lives. Give it a 24-hour lifetime and a reader who upgrades at 09:00 keeps the old answer for 24 hours, while the website — which re-resolves on every request — is correct immediately. Both systems are working exactly as built.

  • Keep entitlement claims out of long-lived tokens. Let the token prove identity and let the access call answer entitlement, so the two can expire on different clocks.
  • If claims must be embedded, make the token short — 5 to 15 minutes, not days — and pair it with a refresh path the app actually exercises on resume, not only on cold start.
  • Re-resolve on the events that matter: app foreground, purchase completion, restore, and any push telling the client something changed.
  • Give support a way to force a re-resolve for one reader. Without it, every one of these tickets ends in asking somebody to reinstall the app, which works and teaches them nothing good.

One resolver, one subject, decisions that expire quickly

  1. Do the identifiers differ? Then it is a merge or a link, not a sync. Fix the account model and the signup flows that created the second record, or the same reader will do it again on their next device.
  2. Do they match but the authorities differ? Point every surface at one access resolver and delete the local interpretations. This is the only fix that stops the class of ticket rather than the instance.
  3. Do they match, with the same authority, but different ages of answer? Shorten the lifetime of the cached decision and add explicit re-resolution triggers. Confirm by forcing a refresh on the stale surface and watching it agree.
  4. Does the disagreement track the reader's network or location? Treat it as institutional access, not as a bug in the app.
  5. Afterwards, add the standing check that would have caught it: a synthetic reader whose entitlement is toggled on a schedule, with every surface asserting the expected answer within its stated freshness window.

The end state is unglamorous and durable: one internal subject identifier, one service that answers what this subject may read right now, and every surface calling it rather than remembering. That resolver is a small, well-bounded piece of software with a genuinely testable contract — the kind of component we build to be owned and extended by the team that inherits it, described in products built to be handed over. The rest of this silo sits under paywalls, subscriptions and entitlements, inside our media and publishing practice.

Frequently asked questions

Short answers to the follow-ups this page tends to raise.

Why does my subscription work in the app but not on the website?

Most often because the app and the website are looking at two different accounts. A subscription bought inside an app arrives as a store receipt tied to a store account, and unless that purchase was connected to a web login, the website has no record of the person in front of it. Compare the internal account identifier on both surfaces before assuming the systems are out of sync.

What should support ask for first on an access mismatch?

The internal subject identifier from both surfaces, shown in a debug or account screen. Email addresses are unreliable — relay addresses, work and personal accounts and address changes all break the join — while the subject id answers in one comparison whether this is one account or two. Add the credential's issue time as the second question.

Why does access come and go depending on where the reader is?

That pattern is institutional access resolved by network address. A seat granted to an organisation by IP range is present on the office network and absent on mobile data or at home, so the same reader is entitled in one place and anonymous in another. It is not a synchronisation failure, and the repair is to bind the entitlement to a person once they have been recognised rather than to the network alone.

How fresh does an entitlement decision need to be?

Seconds on the web and 2 minutes at most inside an app, because a reader who has just paid expects to read immediately. Long-lived tokens carrying entitlement claims are the usual cause of an app being confidently out of date; keep identity in the token and resolve entitlement separately on foreground, purchase and restore.

  • entitlements
  • identity
  • subscriptions
  • mobile apps
// shipped work

The work behind this page

Builds from our portfolio that this page draws on.

Working on something in this space?

Tell us where you are in a sentence or two. We'll tell you honestly whether we're the right team, and what a sensible first slice of the work looks like.

Start the conversation