Shopify App Development in 2026: A Practical Guide
The hard parts of a Shopify app are rarely the features. They are the distribution choice, the review requirements, and the storefront surface you commit to on day one.

On this page
Key takeaways
- The public-versus-custom decision is made before any code exists and determines your review obligations, billing model and support burden.
- Extensions are the modern surface — theme app extensions, checkout UI extensions and Functions replace the old pattern of injecting code into themes.
- Shopify's own requirements checklist is a substantial part of the build, not a formality at the end.
- Performance is a review consideration and a merchant retention issue, because an app that slows storefronts gets uninstalled regardless of its features.
Most people planning a Shopify app underestimate it in a predictable way. They scope the feature accurately and the surrounding work not at all — authentication, sessions, webhooks, billing, the requirements checklist, and the question of where in a merchant's store the app actually appears.
This is a guide to those parts, because the feature is usually the easy half.
Scope
Building an app, not marketing one. The distribution and listing side is a separate discipline covered elsewhere.
The first decision: public or custom
Made before any code exists, and it determines almost everything that follows.
A public app is listed on the App Store, installable by anyone, and subject to Shopify's review and requirements. You get distribution — merchants find you — and in exchange you accept review, a support obligation to strangers, and a product that must work across every theme and configuration you have never seen.
A custom app is built for one merchant. No listing, no App Store review, no unknown themes. You get to make assumptions. You also get no distribution, and if the client leaves, the app has no other market.
Public and custom compared
| Public app | Custom app | |
|---|---|---|
| Distribution | App Store discovery | None |
| Review process | Required | Not required |
| Requirements checklist | Applies fully | Largely not |
| Support burden | Unknown merchants at scale | One known client |
| Billing | Shopify billing API, revenue share | Whatever you agree |
| Theme compatibility | Must work everywhere | One theme |
| Best when | You have a market | You have a client |
The mistake to avoid is building a custom app with vague intentions of listing it later. Retrofitting a single-merchant app into a public one usually means rewriting the assumptions, and the assumptions are load-bearing — one theme becomes every theme, one configuration becomes every configuration, and one known client becomes an unknown support queue.
Where your app actually lives
The surfaces have changed substantially, and code written against the old patterns is a liability.
The embedded admin. Your app's interface inside the Shopify admin, built with Polaris and App Bridge so it feels native rather than like an iframe someone bolted on.
Theme app extensions. How an app renders on the storefront now. App blocks that merchants place through the theme editor, with no code injected into theme files. This is the modern replacement for the old pattern of writing snippets into a merchant's theme, and it is better for everyone: merchants can place and remove your feature themselves, and uninstalling actually removes it.
Checkout UI extensions. Interface elements at supported points in checkout, replacing the old checkout.liquid approach.
Shopify Functions. Server-side logic for discounts, delivery and payment customisation. Since legacy Scripts stopped running on 30 June 2026, this is the supported route for that behaviour.
Admin extensions and POS UI extensions for apps extending those surfaces.
The important architectural point: if your app needs to appear on the storefront, design around theme app extensions from the start. Injecting into theme files still technically works in places and produces exactly the problems merchants complain about — code left behind after uninstall, conflicts with theme updates, and a footprint they cannot control.
The parts that take longer than the feature
Four areas that consistently absorb more time than planned.
OAuth and session management. Straightforward in principle, fiddly in practice. Token storage, session persistence across embedded contexts, handling reinstalls and scope changes.
Webhooks, done reliably. Webhooks can be delayed, duplicated or missed. An app that assumes exactly-once delivery will corrupt its own data. Idempotency and reconciliation are not optional extras.
Billing. The billing API, trials, plan changes, cancellations, failed payments, and what your app does when a merchant downgrades. Build this early; retrofitting it is painful because it touches everything.
Mandatory compliance webhooks and data handling. Customer data requests, redaction, shop redaction. Required, and easy to leave until the review rejects you for it.
Before submitting for review
- Every required webhook implemented and tested, including compliance ones
- OAuth handling reinstalls and scope changes correctly
- Billing covering trials, upgrades, downgrades and failed payments
- Storefront features delivered as theme app extensions, not injected code
- Performance measured on a real storefront, not a development store
- Uninstall genuinely removing your footprint
- Documentation and support contact that a reviewer can actually use
Performance is a product feature
Worth stating separately because it is the most common reason a good app gets uninstalled.
Any app rendering on the storefront adds weight to pages merchants care about. If your app loads a script globally to support a feature used on one template, you are charging every page for something most of them do not use.
The consequences are commercial rather than technical. Merchants increasingly audit app weight, page speed affects their rankings and conversion, and an app that visibly costs them Core Web Vitals is the first one removed when they do a cleanup.
Practical rules: load only where your feature is used, defer everything you can, keep your bundle small, and measure on a realistic storefront rather than a clean development store with nothing else installed.
The review process
Shopify's review is more thorough than most first-time submitters expect, and treating it as a formality at the end is why timelines slip.
The requirements checklist is public. Read it at the start of the project, not the end — a substantial share of it describes things that are architectural rather than cosmetic, and discovering them after the build is how a two-week fix appears.
The common rejection causes are consistent: incomplete or missing mandatory webhooks, billing that does not handle the required cases, an onboarding flow a reviewer cannot complete, insufficient documentation, and storefront implementations that inject code rather than using extensions.
Build against the checklist continuously and the review becomes an administrative step. Build the app and then read the checklist, and it becomes a project. Resubmission after a rejection also costs calendar time you cannot compress, which matters most when a launch is tied to a date someone has already announced.
Supporting an app you did not expect to support
Support is the cost first-time app builders model least accurately, and for a public app it is not optional.
The shape of it is unintuitive. Most tickets are not bugs. They are merchants whose theme does something your app did not anticipate, merchants who have another app touching the same surface, merchants who configured something in a way you did not imagine was possible, and merchants asking questions your documentation answers but they did not find.
Three consequences worth building for:
Make your app diagnosable from the outside. When a merchant reports that something does not appear, you need to determine why without access to their store. Logging that records what your app did for that shop, and a status view inside the app showing its own configuration, turns a two-day exchange into a two-minute answer.
Assume conflicts with other apps. Merchants routinely run dozens. Your app will share a page, a cart, or a checkout with something you have never seen. Defensive rendering, namespaced styles and avoiding global side effects prevent most of the resulting tickets.
Write the documentation before launch. Not because reviewers require it, though they do, but because every question it answers is a ticket you do not receive. The install-and-first-use path deserves the most attention, since that is where merchants abandon.
Reviews are support, visibly
On the App Store your responses to reviews are public and permanent. A merchant who left one star because of a misunderstanding, answered helpfully, becomes evidence that you support your product. Unanswered negative reviews are the first thing a prospective merchant reads.
Decisions that are hard to reverse
Worth deciding deliberately at the start, because changing them later is expensive:
Public or custom, as above.
Where data lives. Your own database is the usual answer, but what you store, and what you rely on Shopify's API for at request time, affects both performance and your compliance obligations. Storing less means fewer obligations and less to redact, but every field you do not keep is an API call on the critical path, and rate limits are real.
Whether you use Functions. If discount, delivery or payment logic is core to your app, that shapes the architecture from day one rather than being bolted on afterwards at considerable cost.
Your storefront surface. Theme app extensions versus anything else. This one is genuinely hard to change and directly affects how merchants experience your app.
Your billing model. Flat, tiered, usage-based. It affects your data model, not just your pricing page.
Your API version policy. Shopify versions its APIs and retires old ones on a published schedule. An app that pins to a version and never revisits it will eventually stop working, and the failure arrives on Shopify's timetable rather than yours. Decide early how you track deprecations and how often you upgrade, because an app carrying three years of accumulated version debt is far harder to move than one upgraded quarterly.
For the public-versus-custom decision in more depth, and the review process specifically, see Shopify development. The performance considerations overlap with storefront and design.
Frequently asked questions
- How long does it take to build a Shopify app?
- A genuinely simple app with one clear function can be a few weeks.
- What is the difference between a public and a custom Shopify app?
- A public app is listed on the App Store, installable by any merchant, subject to Shopify's review and requirements.
- What stack should I use for a Shopify app?
- Shopify's own tooling targets Remix, and their libraries and templates are the least resistance path. Node with any framework is well supported.
- Do I need to use Shopify Functions?
- Only if your app changes discount, delivery or payment behaviour. Since legacy Scripts stopped running on 30 June 2026, Functions are the supported mechanism for that logic.
- How do apps make money on Shopify?
- Through Shopify's billing API, typically recurring subscriptions, often with usage components or tiered plans. Shopify takes a revenue share, and the specifics have changed over time.



Comments