Is a hybrid app noticeably worse than a native one?
For most business apps, no, and users cannot tell. The gap shows in specific places: heavy animation, sustained camera or sensor work, tight integration with platform hardware, and the first weeks after a major OS release when the framework is catching up. If your product lives in those places we will say so and recommend native rather than sell you the thing that is cheaper to build.
What do we actually save by sharing a codebase?
Less than the marketing claims and more than nothing. The screens, the business rules and the API layer are written once, which is the bulk of the work. What is not shared is the platform plumbing at the edges, the store release process, and the testing, which still has to happen on both platforms. The saving is real, it is mostly in the middle of the app, and it compounds over the years of changes that follow launch.
Can we ship to the web from the same codebase?
Often, and it is worth deciding up front rather than discovering later. Where the product is screens over an API, the web build comes largely free and gives you a version that needs no install at all. Where the app depends on device hardware, the web version is a different product wearing the same name, and pretending otherwise produces something that disappoints on every platform.
What happens when the framework has a breaking release?
It gets planned for rather than deferred. Shared frameworks move faster than the platforms underneath them, and an app two major versions behind is an app that is expensive to touch. We keep upgrades on a schedule while they are small, which is the difference between a routine afternoon and a project.
Which framework do you use, and does the choice lock us in?
The choice follows the product rather than a house preference, and the honest framing is that every option here is a commitment you will live with for years. What actually reduces lock-in is not the framework, it is where you put your business rules. Keep them in plain, framework-agnostic code with the shared layer handling presentation and platform access, and a future migration is a rewrite of the outer shell rather than of the product. Scatter framework-specific idioms through your domain logic and you have married it. We structure for the first outcome and tell you plainly what would be involved in leaving.
How do you decide between hybrid and native for our product?
We build the riskiest screen first, on a real handset, and let it decide. Every product has one part that is the actual test: the camera flow, the map with hundreds of pins, the animation somebody is attached to, the offline sync. Arguing about it in the abstract can run for months and produces a decision based on whoever is most confident. Building it takes days and produces a decision based on a thing you can hold. If it performs, the rest of the app is lists and forms and shared code will be comfortable. If it does not, you have learned that before committing a budget rather than after.
Will users be able to tell it is not native?
Not if the platform conventions are respected, and immediately if they are not. What gives a cross-platform app away is almost never rendering performance on a modern phone. It is behaviour: a back gesture that does not work the way the rest of the phone works, a date picker that is neither platform's, a keyboard that covers the field being typed into, transitions that split the difference between two design languages and belong to neither. Those are choices, not limitations, and we make them per platform rather than picking one compromise and shipping it to both audiences.
Can we hire developers for this, or are we dependent on you?
That is a fair thing to ask before committing, and it is a genuine argument in favour of the mainstream frameworks over the interesting ones. A shared codebase in a widely-adopted framework has a real hiring market, and one developer can cover both platforms rather than needing two specialists. The risk is narrower than people fear but it is not zero: you will still occasionally need someone who can write a native module in Swift or Kotlin when the shared layer runs out. We keep those modules small, well-bounded and documented for exactly that reason.