Designing a server for mobile clients
Every released build is a client you still support
On the web you deploy and everyone has the new version. On mobile, releases pass through store review and then reach users gradually, and some never update. So the API is versioned from the first endpoint, and we follow one rule: additive changes only within a version. New fields and endpoints are fine. Removing, renaming or changing the meaning of a field needs a new version. The app sends its build number and platform with each request. The server logs it, and can reply with a soft update prompt or a hard block when a version is retired. That turns a risky cleanup into a planned one.
Change behavior without a store release
Anything likely to change should be data from the server and not code in the app: feature switches, onboarding copy, the order of home screen sections, validation limits, maintenance messages. We expose a small configuration endpoint the app reads at launch and caches. Your team edits it from the admin panel. Store reviewers also need a way in, so we keep a demo account with realistic data and make account deletion available inside the app, which both major stores expect of apps that offer sign-up.
Authentication on a device
The app receives a Sanctum token at sign-in and keeps it in the platform's secure storage. Each device has its own token, named after the device, so a user can sign out a lost phone from another one. Sign in with Apple and Google is handled by verifying the provider's identity token on the server. OTP by SMS is rate limited tightly, because it is the endpoint attackers hit first.
Push that can be trusted
The backend stores one or more device tokens per user and sends through Firebase Cloud Messaging from queued jobs. Tokens that the provider reports as invalid are removed at once. Each send is logged, which makes "I never got it" a question we can answer. Notifications carry a deep link and an ID, and the app fetches the fresh record on open instead of trusting the payload.
Offline first means sync by design
For apps used without signal, the phone keeps a local database and a queue of pending changes. The server provides sync endpoints that return records changed since a cursor, including deletions. Writes carry a client-generated UUID so a retried request is recognized and not applied twice. Conflicts need a rule you can explain to users. Last write wins is fine for a profile. For a job report or an inventory count we merge by field or flag the record for review. Large uploads go straight to storage with pre-signed URLs and resume after interruption.