Written by Technical Team | Last updated 10.10.2025 | 14 minute read
FHIR—Fast Healthcare Interoperability Resources—was designed to make health data exchange faster, safer and more modular. Instead of monolithic documents and bespoke interfaces, FHIR organises clinical information into granular “resources” such as Patient, Observation, MedicationRequest, Encounter and CarePlan. Each resource has a predictable JSON (or XML) structure and is accessed over RESTful APIs with standard HTTP verbs. For a healthcare mobile app development company, this is transformative: it reduces the friction of connecting to electronic health record (EHR) systems, registries and wearables, and offers a common language for data modelling across iOS, Android and backend services.
SMART on FHIR adds the crucial layer of identity and permissions. It standardises how an app securely launches against an EHR or health data host and requests authorisation to read and write specific data using OAuth 2.0 and OpenID Connect. In practice, SMART on FHIR defines a consistent way to discover an authorisation server, request scopes such as patient/*.read, handle patient or practitioner context, and receive a bearer token. When your app uses SMART, it can interoperate with multiple EHRs without rewriting the entire login and consent flow for each vendor.
Together, FHIR gives you the what (resource models and REST endpoints) and SMART provides the how (secure launch, consent and tokens). A capable development company treats both standards as first-class citizens throughout product, design, engineering and operations. That means using FHIR resources for domain modelling from day one, and baking SMART on FHIR flows into the user experience so authentication, consent and data access feel seamless rather than bolted on. It also means anticipating variation: different servers may expose different FHIR versions, profiles and capabilities. The work isn’t just coding to a spec; it’s managing interoperability at scale.
The architectural phase sets the tone for everything that follows. A strong implementation starts with a domain-driven design that maps product requirements to FHIR resources and relationships. If your app needs to show a longitudinal view of vitals, you’ll likely use Observation resources with LOINC-coded values and rely on Encounter and Patient to provide context. For medicines, you’ll consider Medication, MedicationRequest and MedicationStatement, mindful of how different servers encode drug codes and dispense details. Decisions here influence caching strategies, pagination, and error handling on mobile—each resource fetch has a power and latency cost.
Security is more than a tick-box exercise; it’s an end-to-end posture. In a mobile setting, tokens and identifiers must be handled with the same care you reserve for bank cards. A robust approach includes secure storage for tokens (Keychain on iOS, Keystore with StrongBox on Android), transport security with TLS and certificate pinning, and the use of PKCE for public clients. On top of that, the backend should avoid storing raw patient identifiers unless absolutely necessary; where possible, it should operate as a stateless pass-through to the FHIR server, annotating requests with audit metadata and enforcing a least-privilege model based on SMART scopes.
Consent flows should be treated as a core UX, not an interruption. The SMART on FHIR dialogue is part of the clinical safety story: patients (or clinicians) must understand what the app is accessing and why. A thoughtful company designs language and controls that explain the requested scopes in plain English, differentiates between one-time access and ongoing synchronisation, and offers clear ways to revoke consent. If your app will function offline, your consent model must also specify what—if anything—remains on device and how that data is protected with encryption at rest and app-level controls such as passcodes or biometrics.
Interoperability hinges on profiles and terminologies. Profiles constrain base FHIR resources to a particular use case or jurisdiction, while terminologies—SNOMED CT, LOINC, ICD-10 and proprietary code systems—attach semantics to codes. Apps that ignore profiles often run into mismatches (for example, an Observation that should carry a UCUM unit but doesn’t). A best-practice architecture includes a terminology strategy—either an embedded lightweight value set resolver or a connection to a terminology service—and a plan to validate incoming payloads against target profiles. Validation is not merely defensive programming; it’s a way to surface meaningful user feedback when a server returns unexpected shapes.
Finally, architectural plans must account for scale and change. FHIR versions evolve, endpoint capabilities differ, and servers crash. An abstraction layer—sometimes called a “FHIR gateway”—can stabilise your mobile client by normalising capability statements, managing per-server quirks, rate limiting, retry policies, and caching. This gateway also becomes the right locus for advanced functions such as subscriptions for change notifications, deduplication, and clinical summarisation logic that would otherwise bloat the mobile app.
Key architecture decisions a healthcare mobile app development company formalises early:
On-device implementation begins with SMART discovery. The app queries the FHIR server’s .well-known/smart-configuration (or the FHIR server’s CapabilityStatement as a fallback) to locate the authorisation and token endpoints, supported code challenge methods (such as S256 for PKCE), and available scopes. With that metadata, the app constructs an authorisation request that includes the client ID (for public mobile clients, often registered per platform), redirect URI and requested scopes. PKCE adds a code challenge to protect the authorisation code exchange, which is essential for public clients where a client secret cannot be safely embedded.
After the user authenticates with the hosting EHR or identity provider and approves consent, the app receives an authorisation code at its registered redirect URI (using app-claimed HTTPS or a custom URL scheme). It exchanges the code for access and refresh tokens at the token endpoint, binding the request with the original code verifier. At this point, the app stores tokens in secure storage and begins calling the FHIR REST API, attaching the access token in the Authorization: Bearer header. If the SMART server supports context—such as a specific patient record or encounter—the app reads this from the launch parameter or token introspection and uses it to scope subsequent queries.
A well-crafted FHIR client abstracts request composition so screens can focus on intent rather than plumbing. The client understands paging (_count, link[rel=next]), sparse fieldsets (_elements), text-minimised responses (_summary), and inclusion (_include/_revinclude) to reduce round-trips. It also normalises server variability—for example, defensive handling when a server returns numeric IDs instead of UUIDs, or when a capability statement omits a declared searchParam that’s actually supported in practice. Error handling is more than exceptions; it’s user messaging that suggests a safe next step. A “no results” message for a medication list means something very different to a “token expired” message requiring a relaunch.
Caching and synchronisation strategies separate mature apps from prototypes. Mobile networks are uneven and energy-constrained. The client should cache immutable or rarely changing resources (such as Patient demographics) and use ETags or If-Modified-Since headers to avoid unnecessary downloads. For longitudinal data like vitals, the app can ask for changes since the last sync (_since) or subscribe to server-side notifications if supported. Where write operations occur—say, posting a QuestionnaireResponse or a new Observation—the client should queue and encrypt writes for eventual consistency, report status to the user, and reconcile conflicts if a concurrent update happens on the server.
A production-ready app must prove it does what it claims—and that proof has to be repeatable. Technical validation starts with unit and integration tests that exercise resource parsing, date/time handling, bundle processing, and error scenarios. Automated tests should feed representative JSON payloads through parsers and renderers to catch edge cases like missing valueQuantity units or unexpected extensions that can break UI components. End-to-end tests run against sandbox FHIR servers and, where possible, vendor-specific test beds that emulate realistic authentication and data distributions. The aim is not only spec conformance but ecosystem conformance—behaving correctly across multiple server interpretations of the same spec.
Compliance spans privacy, security and clinical safety. In a UK context, that means aligning with UK GDPR and the Data Protection Act, completing Data Protection Impact Assessments, and ensuring patients can exercise subject rights through the app (access, rectification, deletion where appropriate). On the security front, formal threat modelling—think STRIDE or similar—uncovers risks such as token exfiltration via logs, insecure deep-link handlers, or WebView misuse during authorisation. Controls then map to practical mitigations: whitelisting redirect URIs, disabling screenshots on sensitive screens, encrypting SQLite caches, and rigorous logging redaction so no personally identifiable information slips into analytics.
Clinical safety merits particular attention. If the app displays or captures clinical data that may influence decisions, the company should maintain a clinical safety case and hazard log, documenting how risks are mitigated through design and process. Examples include bounds checking on numeric observations, clear labelling of the data source and timestamp, and unambiguous handling of units—avoiding the classic pitfall where a mg/dL value is misinterpreted as mmol/L. Where calculations are involved (for example, early warning scores), the math should be independently verified and regression-tested with known datasets to ensure repeatable accuracy across app versions.
Performance is a user trust issue as much as a technical concern. Long page loads and spinning indicators erode confidence, especially in clinical settings. A development company tunes performance using server and client levers. On the server side, they request appropriate page sizes to balance bandwidth and latency, ask for only essential elements using _elements, and collapse multiple reads into searches with _include when linking related resources. On device, they prefetch key data after login, memoise render-heavy components, and use background tasks to complete synchronisation when the OS permits. Accessibility considerations matter too: clear empty states, tolerant search (for example, supporting NHS-number or date-of-birth lookups where lawful), and offline affordances that explain which features are limited without connectivity.
Operational readiness closes the loop. Continuous integration pipelines run conformance and security tests on every merge, scan third-party libraries for vulnerabilities, and produce signed builds with reproducible versioning. Release processes include staged rollouts, feature flags for risky integrations, and a plan to rollback if user error rates spike. Observability defines what “good” looks like—latency percentiles for key FHIR searches, token refresh success rates, error taxonomies by vendor—and routes alerts to engineers who can diagnose issues without ever seeing patient-identifiable payloads. Every operational step respects data minimisation and the principle that logs are for metadata and metrics, not clinical content.
Taking a SMART on FHIR app live is as much about relationships as it is about code. Each EHR or health data host may require separate client registration, branding review and security attestation. A pragmatic company approaches go-live as a multi-party project: it coordinates timelines with the server operator, agrees on the precise scopes the app will request, and validates test patients and edge cases before enabling real accounts. In parallel, it prepares customer support scripts for common SMART issues—failed redirects, mobile browser blockers, incorrect system time—and equips support teams with non-PII diagnostic artefacts such as correlation IDs.
Monitoring has to be privacy-preserving, high signal and actionable. Metrics should focus on system health and user experience without exposing contents. Typical measures include authorisation success rate, median time from launch to data on screen, FHIR search error rates by code class, and cache hit ratios. Link these to clear SLOs and alert thresholds so that spikes in 429 (too many requests) or unusual 401/403 patterns get attention before users feel the pain. Where the app writes data, add integrity checks—round-trip reads to verify that a posted resource is retrievable and matches expectations—and reconcile discrepancies promptly.
Version drift is inevitable in an ecosystem with many moving parts. Servers will upgrade, add new profiles, or tighten constraints. Plan for it. Feature-detect server capabilities at runtime rather than assuming static behaviour; for example, interrogate the CapabilityStatement on startup and during periodic refreshes to adapt your search parameters or fall back gracefully when a feature is unavailable. Maintain a living compatibility matrix that lists known quirks per vendor—perhaps that one server requires _pretty=false for performance, or that another caps _count at 50 regardless of your request. This matrix becomes institutional knowledge that saves days of debugging.
The people factor matters. Clinicians want tools that present information in context and never surprise them. Patients want clarity about where their data is coming from and where it’s going. Bridge the gap with transparent design and language. Label data sources by provider, show time stamps and units prominently, and explain writebacks plainly—what gets saved, to whom, and how quickly it appears in the record. Provide a visible “disconnect” control that revokes tokens and clears caches. Doing so isn’t just good etiquette; it also reduces support tickets and builds durable trust.
Frequent pitfalls and how an experienced development company mitigates them:
Beyond pitfalls, the playbook emphasises sustainable engineering. Documentation should include API contracts, resource schemas, sequence diagrams for SMART flows, and runbooks for incidents such as authorisation outage, elevated 5xx errors or corrupted caches. Rotate secrets and certificates on a schedule. Keep an eye on library updates for security patches, especially OAuth client libraries and HTTP stacks. And invest in developer experience: a local mock FHIR server, golden test bundles, and simulator scripts for token exchanges shorten feedback loops and reduce regressions.
A well-run deployment also plans for analytics that respect privacy. Aggregate metrics—adoption by feature, retention cohorts, time-to-first-value—help product teams iterate responsibly. Where user research is required, prefer opt-in studies and deidentified datasets. Tie insights back to real-world outcomes: are clinicians saving time retrieving a medication list? Are patients reviewing abnormal results earlier? These are the signals that matter more than vanity counts and show whether interoperability is delivering its promise.
Is your team looking for help with healthcare mobile app development? Click the button below.
Get in touch