Engineering hubs in Dehradun & Bengaluru · Delivering across 10 countries

nitesh@redcubical.com +91 90687 14658

REDCUBICALSYSTEMS

Services / Build

Mobile apps that survive real devices and real reviewers

We build iOS and Android applications in React Native, Flutter, Swift and Kotlin, with offline-first data architecture and a documented conflict policy, APNs and FCM push, deep linking that resolves correctly on cold start, staged rollout with crash gates, and store submission handled by us. The choice of framework is made against your requirements, in writing, with the cost of each named.

  • Framework decision documented, not defaulted
  • Offline conflict policy chosen per entity, not left to chance
  • Performance budgets enforced in CI, not measured after launch
  • Store submission, review responses and phased rollout run by us

At a glance

Cross-platform
React Native (New Architecture), Flutter 3.x
Native
Swift with SwiftUI and UIKit, Kotlin with Compose
Local storage
SQLite, WatermelonDB, Realm, Room, SwiftData
Push and messaging
APNs, FCM, Amazon SNS, OneSignal
Crash and performance
Sentry, Firebase Crashlytics, OpenTelemetry
OS support policy
Current major release plus two prior
Availability target
99.95% on the supporting backend

Decision

React Native, Flutter or native Swift and Kotlin?

Framework selection

Pick React Native when you already have React engineers and want to share validation, models and API clients with the web. Pick Flutter when you want identical rendering on both platforms and a predictable UI layer. Pick native when the app is built around device capability, background execution, or platform surfaces such as widgets, watches and CarPlay.

Mobile framework decision table
FactorReact NativeFlutterNative Swift / Kotlin
Where it genuinely winsTeams with an existing React or TypeScript codebase. Shared domain logic, validation and API clients across web and mobileDesign-led products needing pixel-identical UI on both platforms, complex custom rendering, or heavy animationCamera, audio, Bluetooth LE, background location, HealthKit, ARKit, widgets, watch and TV apps, tight latency budgets
Honest costTwo runtimes to reason about. Native module quality varies. The New Architecture migration is real work. Upgrades across a large dependency tree are the recurring taxDart is a second language for most teams, so hiring is narrower. Larger binary, roughly 4 to 8 MB before your code. Platform-idiomatic behaviour must be rebuilt rather than inheritedTwo codebases, two review cycles, two sets of tests. Feature parity drifts unless deliberately managed. Highest ongoing cost
UI fidelityReal platform components, so it feels native by default. Divergence between platforms must be handled in codeOwn rendering engine. Identical everywhere, which is a benefit and a cost — it will not inherit new OS design language automaticallyPerfect by definition. New OS design language arrives with the SDK
Team you needReact engineers plus one person genuinely comfortable in Xcode and Android StudioDart engineers plus platform-channel capability for native integrationsSeparate iOS and Android engineers, or one very stretched generalist
Cost versus two native appsRoughly 60 to 70 percent to build, 70 to 80 percent over three years once framework upgrades are countedRoughly 60 to 70 percent to build, 70 to 80 percent over three yearsBaseline, 100 percent. Predictable, if expensive
We recommend it whenFeature breadth matters more than device depth and the web team is ReactBrand-controlled UI matters and the team will commit to DartThe app is a device app rather than a screens app, or one platform dominates your revenue

A hybrid is often the correct answer and rarely proposed: cross-platform for the ninety percent of screens that are lists, forms and detail views, with a native module for the one capability that needs it. We also see teams choose cross-platform then write so much platform-specific code that they carry the cost of both. If your feature list is dominated by device capability, name that early.

Architecture

Offline-first, and what happens when two devices disagree

Mobile networks fail in ways desktop networks do not: lifts, tunnels, aircraft, warehouse basements, patchy rural coverage. Offline-first is not a caching feature, it is a data model decision.

What offline-first means

The local database is the source of truth for the UI. Writes are queued with an idempotency key and a version or vector clock, then a background sync engine reconciles with the server. The design work is choosing a conflict resolution policy per entity: last-write-wins, CRDT, operational transform, or server-authoritative. Choose deliberately and write it down.

Conflict resolution strategy comparison
StrategyHow it resolvesData loss riskImplementation costRight for
Last-write-wins (timestamp or version)The write with the highest timestamp or version number replaces the other outrightReal and silent. The losing edit disappears with no user signal unless you add oneLow. Days, not weeksSingle-user-per-record data: personal settings, a user profile, a private draft, a reading position
CRDT (conflict-free replicated data types)Data structures that converge mathematically regardless of merge order. Yjs and Automerge are the practical librariesNone by construction, though the converged result may not be what a human intendedHigh. New storage format, larger payloads, tombstone growth to manageGenuinely collaborative content: shared documents, lists, boards, annotation, whiteboards
Operational transformOperations are transformed against concurrent operations before being applied, preserving intentNone, if the transform functions are correctVery high. Correctness proofs are hard and central coordination is usually requiredRich-text collaborative editing where character-level intent matters. Rarely justified outside that
Server-authoritativeThe client proposes, the server validates against current state and may reject. The client reconciles to whatever the server saysNone, but the user can lose work they typed offline if the server rejectsLow to moderate, and the easiest to reason about and auditMoney, stock, bookings, clinical records, anything with an invariant that must never be violated

Most applications need more than one of these. A field service app we would typically build uses server-authoritative for job assignment and stock movements, field-level merge for job notes, and last-write-wins for user preferences. A single global strategy is usually a sign the question was not asked.

What the sync engine must do

  • Durable outbound queue. Mutations persist in local storage before the UI acknowledges them, so an app kill mid-write loses nothing.
  • Idempotency keys. A client-generated UUID per mutation, so a retry after an ambiguous timeout cannot create a duplicate order.
  • Delta pull with a cursor. Pull changes since a server-issued cursor rather than refetching collections. Include soft-delete tombstones or deletions will never propagate.
  • Bounded retry. Exponential backoff with jitter, a dead-letter state after a defined number of attempts, and a visible way for the user to see and retry a stuck item.
  • Schema migration on device. Local databases outlive app versions. Every release needs a tested forward migration and a defined fallback if it fails.

The user experience of offline

  • Never lie about state. A tick that means "saved on this device" must look different from one that means "confirmed by the server".
  • Show the queue. Users tolerate delay far better than uncertainty. A pending-changes view removes most support tickets.
  • Surface rejections as work, not errors. If the server rejected an offline edit, present it as an item to resolve with the original content preserved and editable.
  • Test on real conditions. Airplane mode is the easy case. The hard case is a captive portal or 2 kB/s of throughput, which we simulate deliberately.

Submission

Why apps get rejected, and how we avoid it

Store review outcomes

Most rejections are not judgement calls, they are checklist failures. The recurring causes are missing in-app account deletion, purchases routed outside the store, privacy declarations that do not match observed network traffic, reviewer-inaccessible content behind a login, and crashes on the reviewer device. We run a written pre-submission checklist covering each one.

Common App Store and Play Store rejection reasons and prevention
Rejection reasonStoreWhy it happensHow we avoid it
No in-app account deletionApple and GoogleThe app allows account creation but only offers deletion by email or web formA deletion flow inside the app that removes or anonymises data, with the retention exceptions stated in plain language on the confirmation screen
Payments routed outside in-app purchaseApple and GoogleDigital goods or subscriptions link to an external checkout, or the app mentions cheaper prices elsewhere in a prohibited wayClassify every purchasable item as digital or physical during design. Digital goods use store billing with working restore. External-link entitlements are applied for where they legitimately apply
Privacy manifest or data disclosure mismatchApple and GoogleThe declared data collection does not match what reviewers observe on the wire, often because an analytics or advertising SDK collects more than the team realisedWe inventory every SDK and its network calls, capture traffic during QA, and generate the privacy manifest and Play data safety form from that evidence rather than from memory
Reviewer could not access the appApple mainlyLogin-walled app with no demo account, expired credentials, SMS OTP the reviewer cannot receive, or geofencing that blocks the review regionA permanent, non-expiring demo account with representative data, a bypass code for OTP flows documented in review notes, and geofencing exemptions for reviewer traffic
Crash, hang or broken flow on the reviewer deviceApple and GoogleUntested OS version, oldest supported hardware, low memory, or an empty-state path nobody exercisedA device matrix that includes the oldest supported hardware and a low-memory Android device, plus automated smoke tests over first-run, empty-state and permission-denied paths
Permission requested without justificationApple and GoogleBackground location, contacts, photos or microphone requested at launch, or a purpose string that restates the permission nameJust-in-time permission requests, purpose strings that state the user benefit, and removal of any permission not tied to a shipped feature
Insufficient functionality or thin web wrapperApple mainlyThe app is a WebView around an existing site with no platform integrationIf the honest answer is that the product is a website, we say so before you commission an app. If a shell is right, it earns its place with offline support, push, biometrics and native navigation

Rejections are recoverable. A rejection answered the same day with the fix and a clear explanation usually clears on the next review cycle. What costs weeks is a rejection nobody owns. Store communication is our responsibility during an engagement, and we keep a written record of every review interaction so the next submission starts from evidence.

Device and OS support policy

Support policy is a commercial decision with an engineering cost, so we make it explicit and revisit it every two quarters against your own analytics rather than a general market chart.

Default device and OS support matrix
DimensionDefault policyWhyReview cadence
iOS versionsCurrent major plus the two before itTypically covers above 95 percent of active iOS devices and keeps you within the SDK features Apple expects you to useAt each September OS release
Android API levelsCurrent API level down to roughly API 26 to 28 depending on your analyticsAndroid upgrade curves are slower and vary hugely by market. Dropping too aggressively cuts real users in India, Africa and Latin AmericaEvery six months
Physical test devicesOne current flagship and one oldest-supported device per platform, plus one low-memory Android handsetCrashes concentrate on constrained hardware. A test fleet of new flagships proves very littleAnnually
Screen classesSmall phone, standard phone, large phone, tablet portrait and landscape, plus foldable open and closed if your analytics show themLayout regressions are the most common visual defect and the cheapest to catch with snapshot testsPer release

Tablet support is the item most often assumed and least often budgeted. A phone app stretched to a tablet reads as unfinished. If tablets matter, they are a design and QA line item, not a checkbox.

Performance

Mobile performance budgets we enforce in CI

A budget that is only measured after launch is an observation. These are checked on every release build, and a regression beyond tolerance fails the pipeline.

How performance is governed

We set numeric budgets for cold start, frame rate, bundle and install size, memory, network payload and battery, measured on the oldest supported device rather than a flagship. Regressions block the release. The reason is simple: performance work deferred until after launch competes with features and always loses.

Mobile performance budgets and measurement
MetricTargetFails the build atMeasured howUsual cause of regression
Cold start to first meaningful frameUnder 1.5 s on current hardware, under 2.5 s on oldest supportedAbove 3.0 s on oldest supportedAutomated launch trace on physical devices, median of 20 runsSynchronous work in application start-up: SDK initialisation, database migration, remote config fetch on the critical path
Scroll and animation frame rate60 fps sustained, 120 fps where the display supports itMore than 1 percent of frames exceeding the frame deadline in a scripted scrollInstrumented scroll test on a long list with real images and real data volumesLayout work per frame, unmemoised list items, image decoding on the UI thread, oversized images
JavaScript or Dart bundle sizeUnder 4 MB for a React Native bundle, under 6 MB for a Flutter release engine plus codeA 10 percent increase versus the previous release without written justificationBundle analyser on every release build, tracked as a time seriesA dependency pulled in for one helper, moment-style locale data, unreferenced assets, duplicated transitive versions
Battery drain in a 30-minute active sessionUnder 4 percent on a reference deviceAbove 8 percent, or any wake-lock held beyond its scripted windowBattery historian on Android and energy log on iOS, scripted journeyPolling instead of push, high-accuracy location left running, unbatched background sync, retry storms without backoff
Crash-free sessionsAbove 99.7 percentBelow 99.5 percent halts staged rollout progressionCrashlytics or Sentry release health, per rollout stageUntested OS version, unchecked optional value, background task exceeding its allotted time
ANR rate (Android)Below 0.3 percent of sessionsAbove 0.5 percent halts rolloutPlay Console vitals per releaseDisk or network I/O on the main thread, synchronous database work during start-up, lock contention

Budgets are agreed with you before implementation and are visible on a dashboard, not buried in a pipeline log. Where a business requirement genuinely justifies exceeding a budget, we record the exception with an owner and a review date. What we do not do is quietly move the number.

Hardening

Mobile security hardening and accessibility

Mobile security posture

On device we use platform key storage, TLS with certificate or public-key pinning, biometric gating for sensitive actions, tamper and root detection, and obfuscation on release builds. All of it runs on hardware the attacker controls, so it raises cost rather than removing risk. Authorisation is always enforced server-side.

What we implement on the client

  • Keychain and Keystore. Tokens and secrets in the iOS Keychain with the appropriate accessibility class, or the Android Keystore backed by hardware where available. Never in shared preferences, never in plain files, never in a JavaScript bundle.
  • Short-lived tokens. Access tokens measured in minutes with rotating refresh tokens and server-side revocation. A stolen device should stop being useful quickly.
  • Certificate or public-key pinning. Pin to an intermediate or a public key rather than a leaf certificate, keep a backup pin, and ship a remote configuration path so rotation does not require an emergency release. Pinning without a rotation plan is a self-inflicted outage waiting for an expiry date.
  • Biometric gating. Face ID, Touch ID or BiometricPrompt in front of sensitive actions, with a passcode fallback and no assumption that biometric success authorises anything on its own.
  • Root and jailbreak signals. Treated as risk signals feeding a server-side decision, not as a local gate. Escalate, step up authentication or limit functionality; do not simply exit.
  • Obfuscation and anti-tamper. R8 and ProGuard on Android, symbol stripping on iOS, integrity checks on release builds. This slows reverse engineering; it does not prevent it.
  • Attestation. App Attest and Play Integrity to raise confidence that a request came from a genuine, unmodified app, verified server-side and never trusted from the client.

Accessibility on mobile

  • Screen reader labels. Every interactive element has an accessible label, role and state for VoiceOver and TalkBack. Icon-only buttons are the most frequent failure we find.
  • Focus and reading order. Logical traversal order, modals that trap focus and return it on dismissal, and announcements for state changes rather than silent updates.
  • Dynamic Type and font scale. Layouts tested at the largest text size, with no fixed-height containers around scalable text and no truncation of essential content.
  • Touch target size. Minimum 44 by 44 points on iOS and 48 by 48 density-independent pixels on Android, with adequate spacing between adjacent targets.
  • Contrast. At least 4.5:1 for body text and 3:1 for large text and meaningful graphics, verified in both light and dark themes.
  • Reduced motion. Honour the system setting. Parallax and large transitions cause genuine nausea for some users.
  • Testing. Automated checks in CI for labels, contrast and target size, plus manual passes with VoiceOver and TalkBack. Automation catches roughly a third of real accessibility failures, so the manual pass is not optional.

Honest answer

When a responsive web app or PWA is the better decision

Web or app

If your users visit occasionally rather than habitually, arrive from search or shared links, and your value is content or a transactional flow, a fast responsive web application will serve them better than an app they must find, install and update. Install friction is real: most people who intend to install an app never finish.

Native app, PWA or responsive web decision table
ConsiderationNative or cross-platform appPWAResponsive web app
DistributionStore listing, review process, install step. Discoverable in store searchA URL, installable to the home screen. No store gatekeeperA URL. Zero friction, fully indexable
Push notificationsFull support with rich content and background handlingSupported on Android, and on iOS 16.4 and later only for a home-screen-installed PWANot available
Device capabilityCamera, Bluetooth LE, background location, biometrics, health data, NFC, widgets, watchCamera and geolocation while in use. Limited and inconsistent beyond that, especially on iOSBasic capture and geolocation with permission
Search visibilityStore search only. App content is largely invisible to web searchFully indexableFully indexable
Right whenRepeat daily use, device capability at the core, offline field work, notification-driven workflowsFrequent-but-not-daily use, mostly online, Android-heavy audience, notifications useful but not criticalOccasional use, content or transactional flows, search-led acquisition, tight budget

The honest limits of a PWA on iOS matter: push requires the user to add the app to the home screen, background sync is not available, and storage can be evicted after periods of disuse. If your iOS users need reliable notifications, a PWA is not a substitute for an app. Anyone claiming full parity has not shipped one to an iPhone-heavy audience.

The sequence we most often recommend

For a new product with an unproven audience, ship a fast responsive web application first, instrument it properly, and learn which journeys people repeat. Then build the app around those journeys with device capability and notifications as the reason it exists. This costs less in total than commissioning an app for a feature set nobody has validated, and it means the app you eventually build is designed around evidence rather than assumption.

Where this does not apply: field operations with genuine connectivity gaps, anything with a hardware or Bluetooth dependency, and products where a competitor's app has already set the expectation. In those cases the app is the product and web is the fallback. We will give you our reading of which situation you are in during scoping, before there is a proposal to defend.

Answers

Mobile app development questions

React Native, Flutter or native — which should we choose?

If your app is mostly forms, lists, feeds and API calls, cross-platform wins on cost and consistency: React Native when you already have a React web team and want to share domain logic, Flutter when pixel-identical UI and predictable rendering matter more than JavaScript reuse. Go native when the app is built around camera, audio, Bluetooth, background location, HealthKit, ARKit, widgets or watch surfaces, or when latency budgets are tight enough that a bridge is a liability.

Is cross-platform genuinely cheaper?

For the initial build, yes: typically 30 to 40 percent less than two native codebases, not the 50 percent the marketing implies, because platform-specific work never disappears entirely. Over three years the gap narrows further, because you carry the framework upgrade tax on top of the two platform SDK upgrade cycles. Cross-platform saves real money on breadth of features and saves nothing on depth.

What does offline-first actually mean in practice?

The app reads and writes to a local database as the source of truth for the UI, and a background sync engine reconciles with the server. Every write carries an idempotency key and a version or vector clock. You must choose and document a conflict policy per entity type. The hard part is not caching, it is deciding what happens when two devices edited the same record.

How long does an App Store review take, and what gets apps rejected?

Apple review is usually 24 to 48 hours, occasionally a week for first submissions or apps touching regulated categories. The recurring rejection causes we see are missing or non-restorable in-app purchases, account deletion not offered in-app, privacy manifest and tracking disclosures that do not match observed network behaviour, login-walled demo content without working credentials, and crashes on the reviewer device. Almost all of it is preventable with a pre-submission checklist.

How do you release safely on mobile when you cannot roll back?

You cannot recall a shipped binary, so the controls sit before and around release: staged rollout at 1, 5, 20, 50 then 100 percent with crash-free-session and ANR gates at each step, server-side feature flags so a bad feature can be disabled without a new build, remote kill switches on risky paths, and a minimum-supported-version endpoint for the rare forced update.

Which OS versions and devices do you support?

Our default policy is the current major OS release plus the two before it, which typically covers above 95 percent of the installed base on iOS and above 90 percent on Android. We validate on a device matrix that includes the oldest supported hardware you actually see in analytics, not just recent flagships, plus one low-memory Android device because that is where crashes concentrate.

Can you make a mobile app impossible to tamper with?

No, and neither can anyone else. Certificate pinning, keystore and Keychain storage, root and jailbreak detection, and code obfuscation raise the effort required and stop opportunistic attacks. All of them run on hardware the attacker controls, so a determined adversary with the device can defeat them. Client-side controls are defence in depth. Authorisation must be enforced server-side.

When is a native app the wrong answer?

When the value is content or transactional web flows, when your users arrive from search or shared links rather than repeat sessions, or when installation friction would cost you more users than a native shell would win. In those cases a fast responsive web app, optionally a PWA with installability and push on both platforms, ships sooner and costs less to maintain. We say so before quoting an app.

Start with a two-week mobile scoping sprint

Fixed fee. You get a framework recommendation with the reasoning written down, an offline and conflict-resolution design, a performance budget, a store submission checklist against your specific category, and a costed delivery plan. The output is yours whether or not you engage us to build it.