Understanding the phone-data pipeline & cursor cache (admin view)

What this article is for

If you administer a MAM-built app, sooner or later you hit some version of this question:

  • “I changed something in the dashboard — why isn’t the app showing it?”
  • “It shows on my device but not on a customer’s. Why?”
  • “How long until everyone sees the update?”

Those are all freshness questions, and you don’t need to read code to answer them. You just need a working mental model of two things: the phone-data pipeline (how your site builds the data the app renders) and the cursor cache (how the platform decides whether to rebuild that data or hand back what the app already has).

This article builds that model in plain language — deliberately operational, enough to reason confidently about what’s fresh, what’s stale, and how to force a refresh, without wading into implementation detail. When you do want that level of detail, the linked reference articles carry the exact, verified specifics.


The one idea underneath everything

A MAM app doesn’t browse your website the way a web page does. Instead, when the app opens — and at points while it runs — it asks your WordPress site one question and gets back one answer: a single bundle of data describing the whole app for the current user. The tabs, the menus, the screens, the buttons, the forms, the notification list, the theme colors, the content.

That bundle is the app. The native iOS and Android shells are mostly empty containers that paint themselves from whatever the bundle says. So the honest answer to “why does the app show that?” is almost always: “because that’s what the last bundle told it to show.” It’s also why your dashboard edits reach the app without an App Store resubmission — you’re changing what the next bundle will contain, not shipping a new binary.

Everything about freshness follows from that one idea. The app is only ever as current as the last bundle it successfully received. So when something looks stale, your job is really just to figure out two things: whether your change made it into a fresh bundle, and whether the device has fetched that fresh bundle yet.


How the bundle gets built: the pipeline, briefly

When the app asks for its data, your site puts the answer together in an orderly, staged process — the phone-data pipeline. You never configure the pipeline directly; it runs on its own. But knowing the rough order of operations explains a lot of what you’ll see.

The pipeline builds the bundle in four stages:

  1. Who’s asking? It figures out the user and their role first. This matters more than most admins expect: the bundle is role-specific. An anonymous visitor, a logged-in customer, and a premium member can each get a different set of tabs, menus, and content from the very same site. So “it works for me but not for them” is very often a role difference, not a bug.

  2. Settings and the cache check. It loads the app’s configuration — theme, layout, the navigation structure — and decides whether it can reuse cached data or needs to build fresh. This is where the cursor (below) gets consulted.

  3. Content. The biggest stage by far. It builds the screens and buttons, the navigation, the forms, and lets each add-on plugin (Reviews, Special Offers, GeoDirectory, Contact Form, and so on) drop its own data into the bundle. If a whole section is missing from the app, start by asking: did that plugin contribute its part here?

  4. Finishing. It assembles the home screen and tidies up the data for the app to consume.

For reasoning about freshness, the detail that matters is the order: the cache check in stage 2 happens before the expensive content-building in stage 3. That ordering is the whole point of having a cache — when the app is already current, the pipeline can answer cheaply and skip the heavy work entirely.


The cursor cache: rebuild, or hand back what they have?

Building a full bundle takes real work from your server, and the bundle itself is large — commonly tens to low-hundreds of kilobytes. Most of the time, though, nothing has changed since the last time that app asked. Rebuilding the whole thing just to hand back an identical answer would waste server time and slow down app launch for no reason.

The cursor is how the platform avoids that waste. Think of it as a single “edition stamp” for your app’s data — one value, stored on your site, that changes whenever your app’s data should count as new.

The flow on each request is simple:

  1. After a successful fetch, the app remembers the edition stamp it received.
  2. On its next fetch, the app sends that stamp back.
  3. Your site compares the stamp the app sent against the current stamp on the site:
    • They match → nothing relevant has changed. The site skips the expensive rebuild and effectively replies “you’re already up to date.” The app keeps showing what it has. Fast.
    • They don’t match → something changed. The site builds a fresh bundle, sends it back with the new stamp, and the app stores that new stamp for next time. Fresh.

That’s the whole model. The cursor exists to answer one question — “is the copy this app already has still current?” — as cheaply as possible, before any heavy work happens. It’s what lets an app feel instant on launch while still picking up your edits promptly.

One nuance worth knowing: each time the stamp changes, it becomes a brand-new unique value — not a higher number. You never have to reason about ordering or timestamps; the only thing that matters is whether the app’s stamp differs from the site’s. Different means rebuild. Same means skip.


What actually moves the stamp

The cache only helps if the stamp reliably changes whenever your app’s data does. The platform moves it in two ways.

Automatically, when WordPress content changes. The platform watches a broad set of ordinary WordPress events and bumps the stamp whenever one fires — for example:

  • A post is published, saved, or deleted
  • Post metadata is added, updated, or deleted
  • A user registers or is deleted, or user metadata changes
  • A category or tag is created, edited, or deleted

The upshot: normal content editing invalidates the cache on its own. Publish a post, edit a user, retag something, and the next fetch from any app sees a new stamp and rebuilds.

Explicitly, when you change app settings. Saving things in the Mobile App Manager — buttons, layouts, images, theme, and similar app-configuration changes — moves the stamp directly. These are exactly the changes you want every app to pick up, so the platform forces a fresh build on the next fetch rather than waiting for a content event.

Put the two together and almost everything you do through the dashboard moves the stamp. That’s the happy path — and why, most of the time, things just update.


So why does a change sometimes not show up?

When a change is being stubborn, work through this short checklist — it maps directly onto the model above.

  1. Has the device fetched again yet? The app only updates when it asks for a new bundle. If it’s sitting open on a screen and hasn’t re-fetched, it’s still showing the bundle it already had — so fully closing and reopening the app (or whatever else triggers a re-fetch) is the first thing worth trying.

  2. Did your change move the stamp? If you edited through the dashboard or normal WordPress editing, it almost certainly did. The risk cases are changes made outside those paths — editing the database or an option directly, or custom code that doesn’t touch a watched WordPress event. Those can change the data without moving the stamp, so apps holding the old stamp keep serving their cached copy until something else bumps it. If you suspect that’s what happened, any small dashboard save will force the stamp to move.

  3. Are you comparing the same role? Because the bundle is role-specific, “it shows for me but not for them” is often just a role difference. Check that your change actually applies to the role the other person has. (See Settings cascade and Role-based settings for how per-role configuration resolves.)

  4. Are you previewing as an admin clone? Admin preview/clone mode deliberately bypasses the cache and rebuilds every time — see the next section for why. That means an admin can see a change land instantly while a normal user on a phone is still a fetch behind. Neither one is wrong: the admin is simply skipping the very cache that keeps everyone else fast.

Working through this list resolves the large majority of “why isn’t it updating?” reports, no code required.


When the cache is skipped entirely

Some requests skip the stamp entirely and rebuild from scratch every single time. Two cases matter to you as an admin:

  • Admin preview / cloning. When an admin previews the app as another role, the platform bypasses the cache so the preview always reflects the absolute latest data. This is why building and tweaking an app through preview feels immediate.
  • A role with caching disabled. There is an app setting — Disable Caching — that turns the cache off for a role. When it’s on, the stamp is reset on every request, so the app’s stored stamp can never match and the site rebuilds the full bundle every time.

Disable Caching is a deliberate trade-off: always-fresh data in exchange for more server work and slower launches. It’s a good temporary, targeted tool — a single role, or a build/debug window where you want every refresh to reflect your latest change. Site-wide in production, it’s usually the wrong choice, because the stamp already invalidates itself promptly whenever you edit content or settings; leaving caching on is the right default for normal end-user roles.

A good rule of thumb: reach for Disable Caching when you need to debug a specific role for a while, then turn it back off.


A note on what’s verified versus aspirational

You might come across internal or developer documentation that describes the cache in more granular terms — per-user stamps, per-section timestamps, sending only the changed sections of the bundle. Treat that as a description of a more advanced design, not what’s running today.

What you can rely on today is the simpler single-stamp model described above: one site-wide edition stamp; when it changes, the next fetch from any app rebuilds the full bundle; when it matches, the rebuild gets skipped. That model is enough to reason correctly about every freshness question you’ll run into as an admin. And if a future release adds finer-grained caching, the reasoning won’t change — “did the stamp move, and has the device fetched?” is still the right question to ask.


How this connects to the rest of the platform

  • App settings (theme, branding, layout, navigation) are the inputs the pipeline reads. Configuring the app in the dashboard is editing what this pipeline builds — and saving those settings moves the stamp.
  • Add-on plugins earn their place in the app by contributing their data during the content stage. If a section is missing, that’s usually the place to look.
  • Roles decide which bundle a given person gets. Freshness and visibility questions frequently turn out to be role questions.
  • The cursor cache is the front door that decides, on every request, whether to do all of that work or skip it.

If you remember nothing else, remember this: the app is a render of one data bundle; that bundle is built for a specific user and role; and a single edition stamp decides whether the site rebuilds it or hands back what the app already has. Almost every freshness question boils down to “did the stamp move, and has the device fetched again?”


  • The phone-data pipeline phases: auth, settings, content, finalize (Concepts) — the four stages, and the cursor short-circuit, at the developer level.
  • Settings cascade: global, per-role, per-button (Concepts) — how role-specific configuration resolves.
  • App settings reference: Disable Caching (App Setting Reference).
  • Cursor cache mechanism (Plugin Reference — mam-main) — the developer-level detail on the cursor and Disable Caching.
Was this article helpful?
Contents

    Need Support?

    Can't find the answer you're looking for? Don't worry we're here to help!