Designing one backend for web, iOS, and Android
How I keep product rules, identity, and data ownership consistent while giving every client a native experience.
- Architecture
- Native mobile
- PostgreSQL
One product model, several interfaces
A shared backend should not force every client to behave like the website. It should define the product rules that must remain true everywhere: who owns a record, which state changes are valid, what data can be exposed, and which actions require server authority.
The web, iOS, and Android clients can then express those rules through platform-appropriate navigation, storage, notifications, and interaction patterns. The contract is shared; the experience is native.
Put invariants below the interface
Balances, order transitions, role permissions, and ownership checks are poor candidates for client-only enforcement. If a rule matters to the integrity of the product, it belongs in the database policy, server function, or another trusted boundary.
That approach made it possible for Spendly clients to share protected finance records and for Chicky Bites clients to agree on the same order lifecycle without duplicating authority in three different applications.
Model workflows, not screens
Tables and endpoints should describe durable concepts such as orders, transactions, accounts, assignments, and status history—not whichever screen happened to be designed first. Screen-led schemas become fragile as soon as another platform needs a different flow.
A workflow-led model also makes background jobs, reporting, and administrative tools easier because they operate on the same domain language as the customer product.
Let clients specialize safely
Native clients still need platform-specific behavior. Sessions belong in Keychain or encrypted Android storage. Push notifications need device-token lifecycles. Offline and retry behavior should respect the platform rather than imitate a browser tab.
The backend contract should make these differences safe by exposing narrow operations and predictable error states instead of leaking administrative credentials or trusting client-supplied ownership fields.
The practical test
I consider the architecture healthy when a new client can be added without inventing a second source of truth, while an existing client can change its interface without requiring a database redesign. Shared rules and native experiences should reinforce each other rather than compete.
