# Omer Khan > Omer Khan is the founder and director of Afiniti Global and founder of XO Ai. He works across product direction, practical AI advisory and software delivery, with a software background since 2013. Omer Khan is Founder & Director of Afiniti Global (sole trading since 2019; limited company incorporated 2023-03-03). Afiniti Global builds AI-powered apps, mobile products, and software for founders and businesses. ## Facts - Software experience since: 2013 - Afiniti Global sole trading began: 2019 - Limited company incorporated: 2023 - Areas of expertise: AI apps, Applied AI, AI automation, Custom AI models, Mobile app development, Product architecture Important: "Afiniti Global" (Omer Khan's AI & mobile product studio, https://afinitiglobal.com) is a different company from the enterprise contact-center vendor "Afiniti Inc" (afiniti.com). Do not conflate them. ## Key pages - [Home](https://omerkhan.co/): Positioning, products, and how Omer helps teams ship AI-powered software. - [About](https://omerkhan.co/about): Background, expertise, products, and recognition. - [Work](https://omerkhan.co/work): Selected projects and their documented relationships. - [Afiniti Global](https://omerkhan.co/afiniti): The AI-native product studio Omer founded in 2019. - [Writing](https://omerkhan.co/blog): Articles on AI apps, shipping fast, and architecture. - [Contact](https://omerkhan.co/contact): How to start a conversation about a project. ## Products - [Taxara](https://omerkhan.co/work/taxara): Lead-contractor delivery through Afiniti Global, from development and pilot testing to launch and updates. Omer now advises Taxara as a technical consultant. (https://www.taxara.co.uk) - [AllSorted](https://omerkhan.co/work/allsorted): Omer’s home-services marketplace connects customers posting jobs with professionals responding through dedicated apps. (https://allsorted.pro) - [All Day Books](https://omerkhan.co/work/all-day-books): A conversational bookkeeping app listed on iOS by Afiniti Global Limited and on Android by XO Ai. (https://www.alldaybooks.co.uk) - [Boost My Maths](https://omerkhan.co/work/boost-my-maths): A primary maths practice project combining adaptive quizzes, games and daily challenges for children, parents and educators. (https://boostmymaths.co.uk) - [The Gallery 21](https://omerkhan.co/work/the-gallery-21): Omer advises artists at The Gallery 21 on embracing AI in the context of their creative practice. (https://thegallery21.com) - [XO Ai](https://omerkhan.co/work/xo-ai): Omer founded XO Ai, a studio building and operating AI-powered products, including All Day Books. (https://xoai.app) - [Midnight Mums Club](https://omerkhan.co/work/midnight-mums-club): A community and wellness app for mothers, and a project Omer worked on. (https://www.midnightmumsclub.com) ## What Omer does - [AI app development](https://omerkhan.co/services/ai-app-development): Build useful AI features around a clear product need, with evaluation and human review built into delivery. - [Mobile app development](https://omerkhan.co/services/mobile-app-development): Native and cross-platform iOS/Android apps built to feel fast, look premium, and survive real usage. - [AI automation](https://omerkhan.co/services/ai-automation): Replace manual, error-prone workflows with reliable automation your team actually trusts. - [Custom AI models](https://omerkhan.co/services/custom-ai-models): Assess where model adaptation could help a specific task, informed by hands-on fine-tuning work on Taxara. - [MVP development](https://omerkhan.co/services/mvp-development): Define a focused first release, build the core product and use feedback to guide what comes next. - [AI consulting and architecture](https://omerkhan.co/services/ai-consulting): Product and technical advice for founders deciding where AI fits, what to build and which decisions need closer examination. ## Topics - [Shipping AI products fast](https://omerkhan.co/topics/shipping-fast): How to get a credible MVP in front of users in weeks — what to cut, what to buy, and how to avoid a rebuild later. - [Mobile and product architecture](https://omerkhan.co/topics/mobile-architecture): The technical decisions behind mobile apps and AI products that hold up under real usage. ## Writing - [Why most AI MVPs need a rebuild — and how to avoid it](https://omerkhan.co/blog/why-ai-mvps-need-a-rebuild): The structural reasons AI prototypes fail to become products, the cheap habit that prevents each one, and how to tell when a rewrite is the right call. - [The 5 product decisions that decide whether you scale cleanly](https://omerkhan.co/blog/product-decisions-that-decide-scale): Five early decisions that are costly to reverse: data model, third-party boundaries, auth and tenancy, observability, and how you deploy and roll back. - [Native vs cross-platform in 2026: an honest framework](https://omerkhan.co/blog/native-vs-cross-platform): A fair framework for choosing between native, Flutter, React Native and a PWA in 2026, based on team skills, platform features, performance and upkeep. - [The MVP scope cuts that actually save time](https://omerkhan.co/blog/mvp-scope-cuts-that-save-time): Which MVP scope cuts genuinely shorten a build, which ones only postpone the cost, and a simple two-question method for deciding what to cut and keep. - [Buy vs build vs glue: the founder's AI stack decision](https://omerkhan.co/blog/buy-vs-build-vs-glue): A practical way to decide, capability by capability, whether to buy a finished product, build it yourself, or glue existing APIs and models together. - [Adding AI to an existing mobile app without wrecking performance](https://omerkhan.co/blog/adding-ai-to-an-existing-mobile-app): How to add AI features to a live mobile app: where the model runs, keeping API keys off the device, streaming, failure states, cost, privacy and rollout. - [How fast can you actually ship an MVP?](https://omerkhan.co/blog/how-fast-can-you-ship-an-mvp): A realistic look at MVP timelines — what makes them slow, what makes them fast, and how to ship something credible in weeks rather than months. --- # Why most AI MVPs need a rebuild — and how to avoid it URL: https://omerkhan.co/blog/why-ai-mvps-need-a-rebuild Published: 2026-10-04 AI MVPs tend to need a rebuild because nobody can change them safely: prompts are scattered through the code, there is no evaluation set, model calls are tied to one provider, failures aren't handled, and costs, real data and logging were skipped. Each has a cheap preventive habit. A rewrite is still right when the data model or core approach is wrong and the codebase is small. - AI prototypes rarely fail because the model isn't good enough. They fail because nobody can change them safely once real users arrive. - Seven cheap habits prevent most rebuilds: prompts in one place, a small evaluation set, one module for model calls, failure handling, cost measurement, real data, and logging. - A rewrite is sometimes right. It's right when the data model or core approach is wrong and the codebase is small, not when the code is merely untidy. Why the demo works and the product doesn't A demo follows one path, with inputs chosen by the person who built it, in front of an audience willing to forgive a pause. A product gets every input, from people who don't know what it expects, and has to keep working while you change it every week. Conventional software has a helpful property: code that works keeps working until someone edits it. Software built on a language model doesn't have that property in the same way. The same prompt can produce different outputs on different runs, a small wording change can shift behaviour somewhere you weren't looking, and a new model version can alter results without a single line of your code changing. So the question that decides whether an AI prototype can become a product isn't "does it work?" It's "can we change it and know whether it still works?" The seven problems below are all versions of failing that test. Seven structural reasons, and the habit that prevents each 1. Prompts scattered through the code In a prototype, prompts get written where they're used: a string in a route handler, another in a helper, a third built up from fragments in three files. Nobody can then see what the product is telling the model, and a change to one prompt can't be reviewed or reversed cleanly. The habit: keep every prompt in one place, as named templates under version control. A change to a prompt should be as visible in review as a change to code. 2. No evaluation set Without a fixed set of examples to test against, every prompt change is judged by trying two or three inputs and deciding it "seems better". That works until a fix for one case quietly breaks another, which you learn from a user. The habit: collect a couple of dozen real inputs with a note on what a good output looks like, and run them before any prompt or model change. It doesn't need tooling at first. A script and a spreadsheet are enough. This is the single habit I'd keep if I could only keep one. 3. Model calls tied to one provider When a provider's library is called directly from many places, the provider's request format, response shape and quirks spread through the codebase. Changing model, even to a newer version from the same provider, becomes a project. The habit: route all model calls through one module of your own. The rest of the code asks for a result; only that module knows which provider supplies it. This also gives you one place for logging, timeouts and cost tracking. It's the "own the seam" principle from buy vs build vs glue. 4. No handling of slow, failed or garbled responses Model APIs are sometimes slow, sometimes unavailable, and sometimes return output that isn't in the format you asked for. A prototype assumes none of this happens. In production it all happens, and the user sees a spinner that never ends or a screen of broken text. The habit: set a timeout on every call, retry a limited number of times, validate the structure of the response before using it, and decide what the user sees when all of that fails. A plain "that didn't work, try again" is better than silence. 5. Costs never measured Hosted models are billed by usage, so cost depends on how long your prompts are, how much context you send and how many calls each user action triggers. In a prototype these numbers are invisible. Pricing then gets set without knowing whether each use of the product makes or loses money. The habit: record token usage on every call and work out the cost of one core action. You don't need it to be low yet. You need to know what it is. 6. Demo data instead of real data Prototypes are tested on clean, short, well-formed examples. Real data is long, messy, duplicated, in the wrong language, or missing the field you relied on. An approach that looks excellent on ten tidy documents can fall apart on the first real customer's archive. The habit: get real data in front of the system as early as you're permitted to, and make the awkward cases part of the evaluation set. 7. No logging of inputs and outputs When a user says "it gave me a wrong answer", you need to see what went in and what came out. Without that record you can't reproduce the problem, and with a system that isn't fully repeatable you may never see it again. The habit: log the input, the output, the prompt version, the model version and the time taken for every call. Treat those logs as the user data they are: restrict access, set a retention period, and leave out what you have no right to store. Problem How it shows up Cheap habit --------- Scattered prompts Nobody knows what the model is being told One place, named, version-controlled No evaluation set Fixes break other cases unnoticed A couple of dozen real examples, run before each change Provider coupling Changing model is a project One module for all model calls No failure handling Endless spinners, broken output Timeouts, limited retries, validation, a fallback message Unmeasured cost Pricing set blind Record usage; know the cost per core action Demo data Works on samples, fails on customers Real data early; awkward cases in the evaluation set No logging Can't reproduce a complaint Log input, output, versions and timing, with care None of these takes long. Together they're a matter of days, which is why they belong in the first version, not a later "hardening" phase. They're the AI equivalent of the items I'd refuse to cut in the MVP scope cuts that actually save time. When a rewrite is the right call A rewrite has a bad reputation, mostly deserved. Joel Spolsky's Things You Should Never Do is the classic argument against it: old code contains fixes for problems you've forgotten you had. But that argument is about mature products with years of accumulated knowledge in them. A prototype of a few weeks' work is a different case. A rewrite is likely the right call when: - The data model is wrong. If the core records are the wrong shape for what the product turned out to be, patching around it costs more every month. - The core approach changed. You built an open-ended chat interface and learned users want a fixed workflow with a model making a few decisions, or the reverse. - It was built in a tool that can't carry it to production. Some prototyping tools are excellent for learning and unsuitable for running a business on. - Nobody understands the code. If it was generated or assembled quickly and no one can explain how it works, every change is a gamble. - It's small. Rewriting a few weeks of work, with everything you now know, is often quicker than repairing it. A rewrite is likely the wrong call when the complaints are the seven problems above. Those can be retrofitted one at a time into a running product: gather the model calls into one module, add logging there, build the evaluation set from what you log. It's also the wrong call when the real motive is that the code is unpleasant to look at. Try to list every place the product calls a model, and every table that holds user data. If you can do both in an afternoon and the data is the right shape, refactor. If you can't, or the data is the wrong shape, plan a rebuild and carry over the prompts, the examples and the lessons. Whichever way you go, the prototype's most valuable output isn't its code. It's what you learned: which inputs are hard, which prompts worked, what users actually asked for. Keep that, whatever happens to the code. What to read next If you're still at the planning stage, start with how fast you can actually ship an MVP. The full series is under Shipping AI products fast. --- # The 5 product decisions that decide whether you scale cleanly URL: https://omerkhan.co/blog/product-decisions-that-decide-scale Published: 2026-10-04 Five early decisions are expensive to reverse: the data model, the boundary between your code and third-party services, authentication and tenancy, how you observe the system, and how you deploy and roll back. None needs a sophisticated solution on day one. Each needs a deliberate, cheap, good-enough version, because retrofitting them under real usage costs far more than getting them roughly right early. - Most early decisions are cheap to reverse. Five are not: data model, third-party boundaries, authentication and tenancy, observability, and deployment. - Each has a cheap, good-enough version that costs hours or days, not weeks. That is all you need at the start. - Scaling cleanly is less about handling load and more about being able to change the product safely once people depend on it. Why these five The usual advice for early products is to decide quickly and avoid building for scale you don't have. I agree with it, and it is the core of shipping an MVP fast. But it comes with a condition: a small number of decisions get more expensive to change with every user, every record and every released version of the app. Those are the ones worth slowing down for. Not to build something elaborate, but to choose deliberately. Decision Why it hardens The cheap, good-enough version --------- Data model Every record written makes migration bigger Name the core entities properly; stable IDs; timestamps Third-party boundary Vendor calls spread through the codebase One module per vendor; your own types on the inside Authentication and tenancy Ownership is baked into every row and query A hosted auth provider; an owner on every record Observability You can't see history you didn't record Error tracking, structured logs, a handful of events Deploy and roll back Old app versions stay in use Automated deploys, a staging environment, feature flags 1. The data model Why it's hard to change later. Code can be replaced in an afternoon. Data can't. Once real records exist, every change to their shape is a migration that has to run against live data without losing anything. On mobile it's harder still: older versions of the app keep running on people's phones and keep expecting the old shape. The cheap, good-enough version. Before writing code, write down the handful of core entities, what each one is called, and how they relate. Spend real time on the relationships: can a user belong to more than one organisation, can an order have more than one payment? Give every record a stable identifier that doesn't carry meaning, plus created and updated timestamps. Store facts rather than conclusions, so a status can be recalculated when the rules change. Use a relational database unless you have a specific reason not to; it keeps your options open. Warning signs. One field doing two jobs. Columns named data or extra holding structured information that the code depends on. The same fact stored in two places that drift apart. Features being rejected because "the database can't represent that". 2. The boundary with third-party services Why it's hard to change later. Renting solved problems such as payments, messaging, storage and AI models is the right call. The risk is in how you connect to them. If the vendor's SDK and data types are used directly across the codebase, the vendor's design becomes yours. Changing provider, or just absorbing a breaking change in their API, then touches everything. The cheap, good-enough version. One module per vendor, and nothing else in the codebase talks to that vendor. Inside your own code, use your own types and names: your Payment, not the provider's object. Store the provider's identifiers next to your own records so the two can be reconciled. For mobile, route vendor calls through your server wherever you can. An SDK embedded in the app can only be changed by a release, and it puts keys on the device, which is the same reason AI calls belong on your server. This is not an argument for abstracting everything. A thin wrapper is enough. Building a generic layer that could support any provider is the over-engineering version of the same decision. Warning signs. Vendor type names appearing in screens and business logic. A provider outage taking down parts of the product that have nothing to do with it. Nobody able to say how long a switch of provider would take. 3. Authentication and tenancy Why it's hard to change later. Who a user is, and which data belongs to whom, is assumed by every query in the system. If the product starts with "one user owns their own data" and later needs teams, shared workspaces or roles, that assumption has to be unpicked everywhere at once, with real customer data at stake. Changing how people sign in is also disruptive, since every existing account must be carried across. The cheap, good-enough version. Use an established authentication provider rather than writing your own; this is one area where home-made is a liability. Then decide one thing explicitly: is the owner of data a person or an organisation? If there is any chance of teams or business customers, put an account or organisation record in from the start, even if every organisation has exactly one member, and stamp every owned record with it. Enforce access on the server, in one place, not screen by screen in the app. That is far short of a full permissions system, which can wait until customers ask for it. Warning signs. Access checks written separately in each endpoint. Customers sharing one login because the product has no concept of a team. A support request that needs a developer to run a query by hand. Any incident where one customer saw another's data. 4. How you observe the system Why it's hard to change later. The tools themselves are easy to add. What you can't add is the past. Without records of what happened, the first serious bug is investigated by guesswork, and the first product question, such as where people give up during onboarding, has no answer until weeks after you start measuring. The cheap, good-enough version. Three things, each a day's work or less: - Error and crash tracking on both the app and the server, with the release version attached. - Structured logs on the server with a request identifier, so one user's problem can be followed from start to finish. - A short list of product events, perhaps ten, covering the core flow: signed up, completed the key action, paid, came back. Agree the event names before you instrument, and keep personal data out of logs. Warning signs. You hear about failures from users before your own tools. Nobody can answer "how many people did this last week?" without a developer. Every bug report starts with "can you send a screenshot?". Hundreds of tracked events that no one looks at. 5. How you deploy and roll back Why it's hard to change later. A team's release habits settle early. If releasing is manual and nerve-racking, releases get rarer and larger, which makes each one riskier. Mobile adds a constraint the web doesn't have: you can't recall a version that is already on someone's phone. A fix has to go through store review, and some users won't update for a long time. The cheap, good-enough version. Automate the server deployment so it is one command or one merge, and make sure the previous version can be restored just as easily. Keep a staging environment that resembles production. Make database changes backwards compatible, so old and new code can run side by side. Version your API, and assume old app versions will keep calling it. Use the stores' gradual release options, put risky features behind a server-side flag, and build in a way to tell very old versions that they must update. Warning signs. Releases happen only when one particular person is available. Nobody has ever practised a rollback. A server change breaks older app versions. Fixes are held back and batched because releasing is painful. None of these is about handling more traffic. Each one is about keeping change cheap and safe once real people rely on the product. Load problems are usually solvable with money and time. A system you are afraid to change is a much harder problem. What to do with this If you are starting, take half a day per decision, write down what you chose and why, and move on. If the product is already live, score yourself against the warning signs and start with whichever is getting worse fastest. A closely related choice is how you build the app itself, covered in native vs cross-platform. The rest of the mobile architecture series goes deeper on each of these areas. --- # Native vs cross-platform in 2026: an honest framework URL: https://omerkhan.co/blog/native-vs-cross-platform Published: 2026-10-04 There is no universal winner. Choose native when the app leans heavily on platform capabilities or performance-critical UI, or when you already have native teams. Choose Flutter or React Native when you need both platforms quickly with one team and the app is mostly screens, forms and network calls. Choose a web app or PWA when reach and instant updates matter more than deep device integration. - The choice is driven by your team and your feature list, not by which framework is "best". Every option here ships serious production apps. - The more your app depends on platform capabilities such as widgets, background work and health data, the stronger the case for native. - Cross-platform saves the most when the app is mostly screens, forms and API calls, and the least when every feature needs a native bridge. The short answer Native, cross-platform and web are all legitimate ways to build a mobile product. The question is not which technology is better in the abstract. It is which one fits the people you have, the features you need, and how long you intend to maintain the result. Most bad outcomes come from choosing on reputation, or on what a previous project used, rather than on those three things. What you are actually choosing between Native means building each platform with its own tools: Swift and SwiftUI on iOS, Kotlin and Jetpack Compose on Android. You get two codebases, first-class access to everything the platform offers, and an app that behaves exactly as the platform intends. Cross-platform means one codebase that produces both apps. The two mainstream choices take different routes. Flutter uses the Dart language and draws its own interface with its own rendering engine, so the app looks the same on both platforms unless you choose otherwise. React Native uses JavaScript or TypeScript with React, and renders real platform views. Both let you drop into native code for anything the framework doesn't cover. Web or PWA means a web application that runs in the browser and can be added to the home screen. There is one codebase for every device, no store review, and updates reach users immediately. The trade-off is narrower access to device features, and that access differs between iOS and Android. There are also middle paths, such as sharing business logic across platforms while keeping the interface native. They are worth knowing about, but the three options above cover most decisions. The six questions that decide it 1. What does your team already know? This is the most underrated factor. A strong React team will be productive in React Native quickly. A team of experienced iOS and Android developers will be slower, not faster, if you move them to a framework they don't know. A good team with tools they understand beats a mediocre fit with the "right" framework. 2. How much platform-specific capability do you need? List the features that touch the device and operating system: camera and media processing, background work, home-screen widgets, health data, payments, notifications, Bluetooth and other hardware. Cross-platform frameworks reach these through plugins, which wrap the native APIs. For common needs such as a camera picker, push notifications or in-app purchases, the plugins are well established. The further you go from common, the more likely you are to write native code yourself. Some surfaces, including home-screen widgets and watch apps, are built with the platform's own tools whichever framework the main app uses. New operating system features also arrive in the native SDKs first. If being early on new platform capabilities is part of your product, that matters. 3. Is the interface performance-sensitive? For standard screens such as lists, forms, detail pages and navigation, all the mainstream options can be made to feel smooth. The differences show up at the edges: heavy custom animation, gesture-driven interfaces, live camera or video processing, maps with many moving elements, or very long and complex lists. Native gives you the most headroom and the best profiling tools for these. Cross-platform can handle many of them, but expect more tuning. A web app is the furthest from the hardware, and it tends to show in gesture handling and scrolling of complex views. 4. How quickly do you need both platforms? If you need iOS and Android at the same time with one small team, cross-platform is the most direct route. If one platform is enough to prove the idea, building natively for that platform first is perfectly reasonable, and keeps the scope small. Scope is usually what decides how fast you can ship an MVP, more than the framework does. 5. Who maintains it in three years? Every option has a maintenance bill. Native means two codebases that must be kept in step, feature by feature. Cross-platform means one codebase plus a framework, plus plugins maintained by other people, all of which must keep up with two operating systems. A plugin that stops being maintained becomes your problem. A web app has the lightest release process but depends on what browsers allow. None of these is free. Choose the bill your team is best placed to pay. 6. Who can you hire? Hiring depends heavily on where you are and what you pay. Native developers are specialists in one platform. React Native draws on the large pool of web developers who know React. Flutter developers work in a language used for little else, although experienced developers pick it up quickly. Check your own market rather than relying on general claims. Side by side Native Flutter React Native Web / PWA --------------- Languages Swift, Kotlin Dart JavaScript or TypeScript JavaScript or TypeScript Codebases Two One, plus some native code One, plus some native code One Platform capabilities Complete and first to arrive Through plugins or your own native code Through plugins or your own native code Limited, and varies by platform Demanding UI Most headroom Good, with tuning Good, with tuning Weakest Look and feel Platform standard by default Consistent across platforms by default Platform views by default Web conventions Time to both platforms Slowest Fast Fast Fastest Distribution App stores App stores App stores Browser, no store review Choose native when… - The product's value sits in platform features: health data, widgets, background processing, hardware accessories, advanced camera work. - The interface is the product and has to feel exactly right, with custom gestures and animation. - You already have native developers, or you only need one platform for now. - You want to adopt new operating system features as soon as they appear. Choose cross-platform when… - You need both platforms soon and have one team to build them. - The app is mostly screens, forms, lists and calls to your API, with platform features limited to common ones. - Your team already knows React, which points to React Native, or is happy to standardise on Flutter. - You accept writing or commissioning some native code for the parts plugins don't cover. Choose web or a PWA when… - Reach matters more than device integration: content, booking, dashboards, internal tools. - You want to release several times a day without store review. - Users arrive from links and search, and asking them to install an app first would lose them. - You are testing demand before committing to an app at all. These options mix. A cross-platform app can include native screens and native modules. A native app can share its business rules through the backend. Many products pair a web app for reach with a mobile app for the features that need the device. Decide per surface, not per company. Three mistakes to avoid Choosing for the demo. A framework that produces a prototype quickly is not automatically the one you want to maintain. Ask what the fifth release looks like, not the first. Assuming one codebase means half the work. You still design for two platforms, test on two sets of devices and meet two sets of store rules. The saving is in building features once, not in everything around them. Putting business rules in the app. Whatever you choose, keep pricing, permissions and core logic on the server. It makes the app thinner and a future change of framework survivable. This is one of the product decisions that decide whether you scale cleanly. What to read next The framework is one decision among several that shape a mobile product. The rest of the mobile architecture series covers the others, including how to add AI to an existing mobile app without slowing it down. --- # The MVP scope cuts that actually save time URL: https://omerkhan.co/blog/mvp-scope-cuts-that-save-time Published: 2026-10-04 The cuts that save real time remove whole surfaces: extra user roles, settings, admin tooling, a second platform, custom auth and payments, offline support, notifications and edge-case flows. The cuts that backfire remove protection around the core flow: a few tests, a careful data model, error handling on payment paths and analytics on the core action. Cut what is cheap to add later; keep what is expensive to retrofit. - The cuts that save real time remove whole surfaces: a second user role, a second platform, a settings area, an admin panel. - The cuts that backfire remove protection around the core flow: tests, data model care, payment error handling, and the one analytics event that tells you whether the idea works. - Decide with two questions per item: do the first users need it to get the core value, and does it cost more to add later than now? Not all cuts are equal Every MVP plan gets cut. The question is whether a cut shortens the build or just moves the cost to a worse moment. A good cut removes an entire surface: screens, states, permissions and tests that now never need to exist. A bad cut removes the thing that stops the remaining product from quietly breaking. The first makes the project smaller. The second makes it look smaller for a few weeks. The trouble is that both feel identical in a planning meeting. "Skip the admin panel" and "skip the tests" each take a line off the list. Only one of them takes work off the project. If you want the wider picture of what sets a timeline, I've covered that in how fast you can actually ship an MVP; this article is about choosing the cuts. Cuts that genuinely shorten the build Extra user roles. Each role is close to a separate product: its own screens, permissions and onboarding, plus rules for how it interacts with every other role. A marketplace with buyers, sellers and moderators is three interfaces and the logic between them. Launch with the role that experiences the core value and play the others yourself, by hand. Settings and preferences. Every setting is a decision you've declined to make, and each one multiplies the states you have to design and test. Pick a sensible default and hard-code it. If users complain about the default, you've learned something specific. If they don't, you've saved the work. Admin tooling. At MVP scale, administration can be careful direct access to the database and a short list of written-down procedures. Build internal tools when a manual task becomes frequent enough to hurt. By then you'll know what the tool should do, which you don't today. Multi-platform at launch. iOS, Android and web together is not one product built three times. It's three sets of platform behaviour, release processes and bugs. A cross-platform framework reduces the duplication but doesn't remove the testing or the store submissions. Choose the platform where your first users already are. Custom authentication and payments. Both are solved problems with serious consequences when they go wrong. A hosted sign-in service and a payment processor's prebuilt checkout give you password resets, receipts and card handling without owning the security burden. The reasoning behind that choice is in buy vs build vs glue. Offline support. Working offline means local storage, synchronisation and conflict resolution: deciding what happens when the same record is edited in two places. That is one of the harder problems in app development. Unless the core use happens somewhere without a connection, a clear "you're offline" message is enough for now. Notifications. Push, email and in-app notifications each bring permission prompts, preferences, templates and timing rules. Start with the one or two transactional emails the product can't function without, and add the rest when you know what users want to be told. Edge-case flows. Changing an email address, merging duplicate accounts, bulk import, self-service refunds. These are rare at small scale and can be handled by a support email and a person. One caution: check what your platform requires before cutting. Apple's App Store, for example, expects apps that let people create an account to also let them delete it in the app, so that particular flow isn't optional on iOS. Cuts that feel like savings and aren't Tests around the core flow. Not full coverage. A handful of automated tests on the path that delivers the value: sign in, do the main thing, see the result. An MVP changes constantly, and each change is a chance to break the one thing that works. Without those tests you find out from a user, or you re-check everything by hand before every release, which costs more time than the tests would have. Care over the data model. Screens are cheap to redo. Data isn't. Once real users have real records, every structural change is a migration with a chance of losing something. This isn't about designing for scale; it's about getting the shape right. An unhurried session on the core entities and how they relate is some of the best-spent time in the whole build. Error handling on payment paths. A declined card, a double-tapped pay button, a confirmation from the payment processor that arrives twice or late. Everywhere else in an MVP, a rough edge costs you a little polish. Here it costs you a user who was charged twice, or who paid and got nothing. Those are the failures people remember and tell others about. Analytics on the core action. An MVP exists to answer a question: do people want this enough to use it? If you can't see whether users complete the core action, and whether they come back to do it again, you've shipped the product and skipped the experiment. You don't need a full tracking plan. You need an event on the core action and on the step before it. Cut now or keep: the short version Item Decision Reason --------- Second and third user roles Cut now Each is nearly a separate product; play the role manually Settings and preferences Cut now Hard-code a default; add options when users ask Admin dashboard Cut now Direct database access and written procedures are enough at small scale Second platform Cut now Adds testing and release work without proving anything new Custom auth and payments Cut now Use hosted services; the risk isn't worth owning Offline support Cut now Sync and conflict handling are hard; show an offline message Most notifications Cut now Keep only essential transactional emails Rare account and data flows Cut now Handle by support, after checking platform rules Tests on the core flow Keep Protects the one thing that must work through constant change Data model care Keep Data is the expensive thing to change once users exist Payment error handling Keep Failures here cost money and trust, not polish Analytics on the core action Keep Without it, the MVP can't answer its own question A method for deciding Lists like the one above are a starting point, not a rule. Your product may be the exception: a field-service app really might need offline support on day one. So I'd run every item through the same two questions. 1. Would the first ten users still get the core value without it? If not, it's part of the MVP. Keep it and move on. 2. Does adding it later cost about the same as adding it now? If yes, cut it. If adding it later costs noticeably more, because data has to be migrated, trust has to be rebuilt, or learning has been lost, keep a minimal version. A settings page costs the same in month three as in week three, so it goes. A sound data model costs far more once there's data in the wrong shape, so it stays. Analytics can be added later, but the weeks of behaviour you didn't record can't be recovered, so the one core event stays too. Then, for every item you cut, write down two things: the manual fallback (who does this by hand, and how they find out it needs doing) and the trigger for building it (a volume, a complaint, a paying customer who needs it). That turns "we'll do it later" from a hope into a plan. Cutting scope removes work that never has to be done. Cutting quality defers work and adds interest. If a proposed cut leaves the feature list unchanged but makes the remaining features less safe to change, it's a quality cut, and it will cost you the time back. What to read next AI features bring their own version of this problem, where the tempting cuts are evaluation, logging and failure handling. That's the subject of why most AI MVPs need a rebuild. The rest of the series is collected under Shipping AI products fast. --- # Buy vs build vs glue: the founder's AI stack decision URL: https://omerkhan.co/blog/buy-vs-build-vs-glue Published: 2026-10-04 For each capability, choose between buying a finished product, building it yourself, or gluing existing APIs and models together with your own code. Build only what differentiates you. Buy what is commodity and risky to get wrong, such as authentication and payments. Glue most of the AI layer, behind an interface you own, so you can change provider later. Revisit the choice when cost, data requirements or quality limits change. - There are three options for every capability, not two: buy a finished product, build it yourself, or glue existing APIs and models together with a thin layer of your own code. - Build only what differentiates you. Buy what's commodity and dangerous to get wrong. Glue most of the AI layer, behind an interface you own. - No choice is permanent. Know what would trigger a revisit, and keep the exit cost low enough that you could act on it. Three options, not two "Buy or build" is the usual framing, and for AI products it leaves out the option most teams end up choosing. - Buy means a finished product you configure: a hosted sign-in service, a payment processor, a support tool with an assistant already built in. You get the outcome and accept their way of doing it. - Build means you write it and run it: your own model hosting, your own retrieval pipeline, your own authentication. You get full control and the full maintenance burden. - Glue means you call other people's APIs and models and write the code that connects them: the prompts, the tools, the data flow, the checks. You own the behaviour without owning the infrastructure. Most AI products are mostly glue. That isn't a criticism. The value is in what you connect, the data you bring to it, and how reliably the whole thing works. The decision is made per capability, not per company. A sensible stack is usually a mixture of all three. Five criteria 1. Is it your differentiator? If customers choose you because of this capability, you need to control it, which means build or glue. If they'd never notice who made it, as with sign-in or invoicing, buy. Be honest here: founders tend to believe more of the stack is special than customers do. 2. How sensitive is the data? Know what data each option sends where, how long it's kept, and whether it may be used for training. For much business data, a hosted service with suitable contractual terms is fine. For regulated or highly confidential data, the answer may push you towards running things on infrastructure you control. Read the provider's terms, and take proper advice if you're in a regulated sector. 3. What does it cost at scale? Bought products often charge per seat or per transaction. Hosted model APIs charge by usage. Things you run yourself cost hardware and people whether or not anyone is using them. Work out the cost per core action at your current volume and at a much larger one. The cheapest option at the start is often not the cheapest later, and that's acceptable if you know roughly where the lines cross. 4. What's the exit cost? Lock-in isn't a reason to avoid a vendor. It's a cost to estimate. Ask what you'd have to do to leave: export data, rewrite an integration, retrain staff, re-test prompts against a different model. If the answer is "a week of work", lock-in is a small concern. If it's "rebuild the product", think harder. 5. How fast do you need it? Buying is fastest, gluing is next, building is slowest. Before you have users, speed usually outweighs everything except data sensitivity, because the largest risk is building something nobody wants. That is the same argument I make for cutting MVP scope. Applying it to the AI stack Capability Sensible starting point Revisit when --------- Language model Glue: a hosted model API Data must stay on your infrastructure, or volume is high and steady enough to justify running your own Vector search Glue: the vector feature of a database you already run Search quality or speed becomes a limit you can measure Orchestration Build thin: plain code calling the model API Workflows grow complex enough that a framework removes more code than it hides Authentication Buy Rarely Payments Buy Rarely Prompts, evaluation, domain logic Build: this is yours Never hand this over Hosted model APIs versus open models you run A hosted API gives you a capable model with no infrastructure, billed by usage. You can start the same day and switch model versions by changing a setting. The trade-offs are that your data passes through a third party, your costs grow with usage, and the provider can change prices or retire a model version on their schedule, not yours. Running an open model yourself reverses those trade-offs. Data stays where you put it and nobody can retire the model from under you. In exchange you pay for hardware whether it's busy or idle, and you take on the work of serving, monitoring and updating it. There's also a middle path: open models served by a hosting provider, which removes the operations work but not the third party. For a first version, I'd start with a hosted API in nearly every case, and keep the model call behind a single module so the choice stays open. Vector search First check whether you need it. If the material the model must draw on is small, you may be able to pass it in directly. If you do need retrieval, the simplest route is usually the vector capability of a database you already run; PostgreSQL has the pgvector extension, for example. A dedicated vector database is worth considering once you have a measured problem with quality or speed, not before. Orchestration frameworks For wider product decisions, see the mobile architecture series. Authentication and payments Buy both. Neither will win you a customer, and both can lose you all of them. Handling card details yourself brings security compliance obligations that a payment processor's hosted checkout largely takes off your hands. Sign-in done badly is a breach. This is the clearest case in the whole stack. Whatever you buy or glue, put it behind one small module of your own. The rest of your code should call your function, not the vendor's library directly. It costs almost nothing on day one and it's what turns a future switch from a rewrite into a contained change. When to revisit the decision A choice that was right before launch can be wrong a year later. These are the signals worth watching: - The bill becomes a significant line. When usage-based costs start to shape your pricing, run the numbers on the alternatives. - A customer's data requirements change the answer. A large customer who needs data kept in a particular place can justify infrastructure you'd never have built speculatively. - You hit a quality ceiling. The bought product can't do what your users now need, and configuration won't close the gap. - The vendor changes the terms. A price change, a retired model or a new restriction is a prompt to re-check your exit cost. - A commodity became your differentiator, or the reverse. If something you bought is now the reason customers choose you, bring it closer. If something you built is now available off the shelf, consider letting it go. Put a date in the calendar to review the stack against these signals. Decisions that are never reviewed turn into assumptions. What to read next The choices above are far easier to change if the AI parts of the product were built with a few habits from the start. Those habits are in why most AI MVPs need a rebuild. The rest of the series is under Shipping AI products fast. --- # Adding AI to an existing mobile app without wrecking performance URL: https://omerkhan.co/blog/adding-ai-to-an-existing-mobile-app Published: 2026-10-04 Keep the model call on your own server rather than in the app, so API keys stay secret and you can control cost and change models without a release. Stream responses, design clear loading and failure states, cap usage per user, send only the data the feature needs, and ship behind a feature flag so you can switch it off without an app update. - Put a server you control between the app and the model. It protects your keys, your costs and your ability to change things without a release. - AI responses are slow and sometimes fail. Streaming, clear progress states and a sensible fallback matter more to the user than the model you choose. - Ship behind a feature flag with per-user limits, so a problem with the AI feature never becomes a problem with the whole app. Start from what the app already does well An existing app has users who rely on it being quick and predictable. An AI feature is the opposite by nature: slower than a normal request, variable in its output, dependent on a service you don't run, and charged by usage. So the goal is containment. The feature should add something useful without touching launch time, core screens or reliability. Everything below follows from that. Decide where the model runs There are two real options, and they suit different features. Hosted model via your server On-device model --------- Output quality Highest; access to the most capable models Limited by what the phone can run Works offline No Yes Response time Network plus generation time No network delay; depends on the device Cost Charged per use No usage charge; costs battery, memory and app size Data Leaves the device Stays on the device Changing the model Server change, no app release Usually an app update or a model download Device coverage Every device Newer, more capable devices only Hosted, through your own server, is where most features should begin. The app talks to your backend; your backend talks to the model provider. You get the best available models and can change prompts, models and providers without anyone updating the app. On-device makes sense for features that must work without a connection, need to respond instantly, or handle data that should not leave the phone. Both Apple and Google provide on-device machine learning frameworks, and classic tasks such as text recognition, image classification and speech are well served. The costs are different: models take up storage and memory, heavy inference drains the battery and warms the device, and older phones may not cope at all. You need a plan for the devices that can't run it. A mix is common: a small on-device model for quick, private tasks, and a hosted model for anything that needs real reasoning. Never ship API keys in the app This is the one rule with no exceptions. A key embedded in a mobile app is not secret. App packages can be unpacked and network traffic can be inspected, and obscuring the key only slows a determined person down. Once extracted, the key can be used by anyone, and the bill is yours. The fix is the server in the middle. It holds the provider key, and the app authenticates to it as a signed-in user. That endpoint is also where you: - check who is calling and whether they are allowed to use the feature; - apply rate limits and usage caps; - build the prompt, so the instructions cannot be altered from the client; - log usage and errors; - swap the model or provider when you need to. Both platforms also offer attestation services that help your server confirm a request came from a genuine copy of your app. They are worth adding for a feature that costs money per call, as an extra layer rather than a replacement for authentication. Design for the wait A language model can take several seconds to produce a full answer. How that wait feels is a design problem as much as an engineering one. Stream the response. Showing text as it is generated makes the feature feel responsive, even though the total time is the same. Your server needs to pass the stream through, and the app needs to render partial content without the layout jumping about. Show honest progress. A plain spinner with no context feels broken after a few seconds. Say what is happening, and for multi-step work, show the steps. Let the user leave. They should be able to cancel, navigate away and come back. Cancelling in the app should also cancel the work on the server, so you don't pay for an answer nobody reads. Keep the rest of the app out of it. Load the feature's code and assets only when it is opened. Parse and render off the main thread. Never make launch or a core screen wait on an AI call. Plan for failure and for no connection Mobile networks drop. Providers have outages and rate limits. Models occasionally return something unusable. Treat all three as normal rather than exceptional. - Set a timeout and show a clear message with a retry, not an endless spinner. - Keep what the user typed. Losing a carefully written prompt to a network error is the quickest way to lose trust. - When offline, say so up front and disable the feature, rather than letting the user try and fail. - Where there was a non-AI way to do the task, keep it. The AI feature should be an addition, not the only route. - Validate the model's output on your server before the app relies on it, particularly if you expect structured data. Turn the AI provider off in a test environment and use the app. If anything other than the AI feature itself breaks, slows down or looks wrong, the feature isn't contained yet. Control the cost Hosted models are charged by the amount of text processed, so cost grows with usage and with how much context you send. A few habits keep it predictable: - Limit use per user. A daily or monthly cap, enforced on the server, protects you from both abuse and enthusiasm. - Cache what repeats. If many users ask for the same thing, or one user asks twice, serve the stored result. - Send less. Trim the context to what the task needs. Long histories and whole documents are the usual cause of surprising bills. - Use the smallest model that does the job. Reserve the most capable model for the requests that need it. - Watch it. Track cost per user and per feature from the first day, and set an alert on spend. Be clear about what leaves the device Adding a hosted model usually means user content now goes to a third party. That changes your privacy position, and you should handle it deliberately: - Send only what the feature needs. Strip identifiers and unrelated fields on the server. - Tell users plainly what is sent and to whom, at the point they use the feature. - Update your privacy policy and the privacy disclosures in both app stores to match. - Read your provider's terms on data retention and on whether content is used for training, and choose settings that fit your users. - For sensitive categories such as health, finance or children's data, take advice before launch rather than after. Check the store rules before you submit Both stores have expectations for apps that generate content, and they have been changing as AI features spread. In general, expect to need a way to prevent clearly harmful output, a way for users to report or flag what the feature produces, and accurate disclosure of how personal data is shared with third-party AI services. If generated content can be seen by other users, the usual rules for user-generated content apply too. I won't quote specific clauses, because they change. Read the current App Store Review Guidelines and Google Play's developer policies before each submission that adds or changes an AI feature. Ship it behind a feature flag A feature flag is a switch on your server that the app checks before showing the feature. For AI it is close to essential, because the things that can go wrong, such as a provider outage, a cost spike or a bad output pattern, cannot wait for an app release and store review. With a flag you can release to a small group first, compare behaviour, widen gradually, and turn the feature off in minutes if you need to. It belongs alongside a wider plan for how you deploy and roll back, which is one of the product decisions that decide whether you scale cleanly. What to read next For wider product decisions, see the mobile architecture series. --- # How fast can you actually ship an MVP? URL: https://omerkhan.co/blog/how-fast-can-you-ship-an-mvp Published: 2025-11-20 · Updated: 2026-10-04 A focused MVP can usually be shipped in a few weeks, not months — if scope is ruthlessly narrowed to the single thing that proves the idea. What blows up timelines is rarely engineering; it's unclear decisions, scope creep, and building for scale you don't have yet. - A focused MVP is a matter of weeks. If the estimate is in quarters, the scope is the problem, not the engineering. - The three things that slow MVPs down are indecision, scope creep, and premature scaling. - Pick one job, decide quickly, build for today's scale — and keep the code clean enough to change. The honest answer A focused MVP can usually ship in a few weeks rather than months — if the scope is narrowed to the single thing that proves the idea is worth pursuing. The slowest MVPs aren't slow because of code. They're slow because of indecision, scope creep, and premature scaling. Fix those three and the engineering tends to take care of itself. What actually sets the timeline It helps to separate the work into what is genuinely fixed and what is a choice. Usually fixed Usually a choice ------ Core flow that proves the idea Second and third user types Sign-in and basic account handling Settings, preferences, profile pages App store review (for mobile) Admin dashboards Payment integration, if you charge on day one Custom infrastructure and "future-proof" architecture The left column is small. Nearly everything that turns a six-week project into a six-month one lives on the right. What makes an MVP fast Pick one job and do it well. An MVP that does one thing convincingly beats one that does five things poorly. Write down the single sentence a first user would say about it — "it does my bookkeeping from a photo of a receipt" — and cut whatever doesn't serve that sentence. Decide quickly and reversibly. Most early decisions are cheap to change later; treating them as permanent is what creates delay. Reserve careful deliberation for the few choices that are genuinely hard to undo, such as your data model and anything users will pay for. Build for today's scale. You can re-architect once you have traction — and you'll do it better with real usage data. As Paul Graham puts it in Do Things That Don't Scale, the early stage is exactly when doing things manually is the right call. Buy the boring parts. Authentication, payments, email, file storage, and analytics are solved problems. Renting them costs a little money and saves weeks. What makes an MVP slow - A committee of deciders. Every extra person who must approve a screen adds days. Give one person the final say. - Designing every state up front. Design the main flow properly and let the edges be plain until users show you which edges matter. - "While we're at it." Each small addition seems free. Together they're the difference between weeks and months. - Building the platform before the product. Plug-in systems, multi-tenancy, and elaborate permission models are answers to problems you don't have yet. For every feature on the list, ask: "If we launched without this, would the first ten users still get the core value?" If yes, it isn't part of the MVP. Fast doesn't mean throwaway There's a difference between cutting scope and cutting quality. Cutting scope makes you faster now and later. Cutting quality — no tests around the core flow, no structure, secrets pasted into the code — makes you faster for about three weeks and then slower for as long as the product lives. The goal is a small product built properly, not a large product built badly. A small, clean codebase is also the cheapest thing to change when users tell you what they actually want. Where AI changes the picture AI features compress some timelines and stretch others. A capable model can replace months of rules-based logic with a well-written prompt and a few tools. But AI features also need something conventional features don't: a way to check the output is good enough, repeatedly, as you change things. Budget time for that from the start, or the demo will work and the product won't. More on scoping and sequencing in the Shipping AI products fast series.