About this article
This article is the first deep dive in the “System Architecture” category of the Architecture Crash Course for the Generative-AI Era series, covering the application form that gets decided first in system architecture.
PC-installed app, browser-based, or smartphone app — the answer to this question binds nearly every downstream design decision: who you hire, how you sell it, what your exit cost looks like. This article covers Native / Web (SaaS/PaaS/IaaS/FaaS) / Hybrid, the inner subdivisions, and case-by-case selection criteria.
More articles in this category
“So where does this system run?”
The question always asked in the first week of any new project. It’s not just a technology choice — it determines the shape of the business itself. Selling as a PC app vs offering as a subscription web service vs distributing as a smartphone app: each answer reshapes the engineer skill set, the sales motion, and the customer-support model.
Until the 1990s, “applications” meant boxed software bought at retail and installed. Web apps became viable in the 2000s with broadband and browser maturity. The iPhone in 2007 opened the smartphone-app market. Cloud adoption in the 2010s turned server procurement into pay-as-you-go. The wider the choice, the heavier the cost of getting it wrong.
Form cannot be fixed after the fact. Trying to fix it requires the will to rebuild from scratch. Migrating a Web app to native later — UI rewrite, offline support, store review — costs roughly the same as a new project. Form selection deserves more care than any other technical decision; if you can’t articulate the choice in the first week, postponing the start by a week is cheaper.
The three basic forms
flowchart LR
USER([User device])
SERVER([Server])
NATIVE["Native<br/>(Runs on device)<br/>Windows/iOS/Android"]
WEB["Web<br/>(Runs on server)<br/>Gmail/Notion/Slack"]
HYBRID["Hybrid<br/>(On device + Web tech)<br/>Electron/Flutter/RN"]
USER -.|Fast, hardware control|.- NATIVE
USER -.|Zero distribution friction|.- WEB
USER -.|Distribution + cross-platform|.- HYBRID
NATIVE -. install .-> USER
HYBRID -. install .-> USER
WEB --> SERVER
classDef native fill:#dbeafe,stroke:#2563eb;
classDef web fill:#fef3c7,stroke:#d97706;
classDef hybrid fill:#fae8ff,stroke:#a21caf;
class NATIVE native;
class WEB web;
class HYBRID hybrid;
| Form | Runs where | Examples |
|---|---|---|
| Native app | Client device | Windows software, iOS apps |
| Web app | Server-side | Gmail, Notion, Slack (web) |
| Hybrid app | Client device (Web tech) | Electron, Flutter, React Native |
This split is by “where does the code run.” Native runs directly on the user’s device. Web runs on a server and ships results to the browser. Hybrid is the middle ground: “runs on device but built with Web tech.”
The location of execution propagates through distribution method, performance characteristics, update workflow, and platform dependency. “Just pick whatever” is wrong. Projects that start without articulating why this form get warped mid-design. Build the prototype in the final form — the prototype tends to become production.
Native applications
A native application runs directly on top of the device’s OS (Operating System — Windows, macOS, iOS, etc.). Windows .exe, macOS .app, iOS/Android apps. Anything not going through a browser falls here.
Most of computing history was native-led. From 1970s mainframes through 1990s PCs, “using software” meant “installing from physical media.”
Native subtypes:
- PC software (accounting, image editing, games, etc.)
- Smartphone apps (LINE, Instagram, camera apps)
- Embedded systems (ATMs, vending machines, in-car nav)
- Batch processing (nightly batch, ETL)
Native’s biggest weapons are performance and direct hardware control: GPU (Graphics Processing Unit) for real-time rendering, raw camera-sensor access, fine-grained Bluetooth control, full-speed local storage. These cannot realistically be done through a browser sandbox (the security mechanism limiting Web code’s execution privileges). Video editors, games, 3D modeling, embedded devices, and high-frequency trading still belong to native.
The weakness concentrates around distribution and updates: store-review delays, prompting users to update, OS-specific implementations. Teams that have waited two weeks on App Store review only to be rejected stop picking native casually. Web and hybrid spread because they escaped these chains. But native still has problems only it can solve.
Embedded, gaming, creative — still native’s territory. If 0.1-second latency or direct hardware control is in play, pick native without hesitation.
Web applications
A Web app runs HTML, CSS, and JavaScript in the browser. Gmail, Notion, Google Docs, Slack, Figma. Open the URL and use it — no install, no update prompt. That “zero-friction delivery” has fixed Web as the default candidate for new projects.
Two technical inflection points:
- Ajax (Asynchronous JavaScript and XML — async communication without full page reload) around 2005, enabling “update the screen without navigating” and bringing near-native interactivity to the Web.
- SPA (Single Page Application — all navigation handled within a single loaded page) maturing in the late 2010s, producing “Web but feels like an app” products like Gmail and Notion.
From the developer’s view, Web’s biggest weapon is structural: distribution friction goes to zero. One deploy and every user is on the latest version. Find a bug, ship the fix in 30 minutes. The lean development cycle this enables is a major reason SaaS exploded over the past 20 years.
Web apps subdivide into four service models:
- SaaS (Software as a Service) — finished application provided as-is.
- PaaS (Platform as a Service) — development platform rented out.
- IaaS (Infrastructure as a Service) — virtual servers rented out.
- FaaS (Function as a Service) — submit just a function, runs only when called.
Vehicle analogy: SaaS is a dispatch taxi, PaaS is car-share, IaaS is a monthly parking lot, FaaS is on-demand taxi. The only difference is how much you want to maintain yourself. The choice trades scope of management (= responsibility) against degree of freedom.
Web’s strength is the single point of “no install, instant delivery.” All business advantages chain off that.
SaaS
SaaS rents finished applications over the Internet. Gmail, Notion, Slack, Google Workspace, Salesforce. Browser + login = usable in one second. Software is “used,” not “owned”, billed monthly or annually.
The substantive innovation isn’t “runs on the Web” — it’s multi-tenant architecture: one application serving multiple customers (tenants) with logically isolated data, sharing common infrastructure across all customers. When Salesforce introduced this in 1999, traditional packaged-software vendors dismissed it as “unthinkable to put data on shared servers.” Today most business software has fully migrated to SaaS.
| Pros | Cons |
|---|---|
| Available worldwide | Low customizability |
| No install needed | Vendor outages affect you |
| Independent of client performance | Vendor lock-in |
| Always latest features | Recurring fees, no offline |
The technical definition (multi-tenant) and the business definition (any subscription web service) often diverge. When someone says “this is also SaaS,” confirm which sense they mean. Single-tenant (an isolated instance per customer) explodes the operational burden, often degenerating into custom-build territory. Mixing them up will throw your estimate off by an order of magnitude.
For a new B2B/B2C product, defaulting to SaaS-only is the rule. If you can’t write the reason to skip it in 1 minute, don’t skip it.
PaaS
PaaS rents the entire app runtime. OS, middleware (software between OS and app providing shared functionality), runtime (the system that executes programs), scaling (auto-adjusting server count under load) — pre-configured. Developers just write code. git push and the deploy is done; load goes up and instances scale automatically. Heroku (launched 2007) cemented this experience.
PaaS’s substance is removing “OS and middleware fiddling time” from the developer’s job. Server-OS updates, nginx (high-performance web-server software) configuration, automatic SSL renewal, deploy scripts — these tasks unrelated to the app’s core value get delegated to the PaaS vendor.
| Pros | Cons |
|---|---|
| Higher dev productivity | Less freedom than IaaS |
| Lower cost (no upfront) | Vendor lock-in |
| Easy environment cloning | Cannot run offline |
| Auto-scaling | Hard to handle unique requirements |
Examples: Heroku (the original; lost ground for personal use after free-tier removal in 2022), Vercel (Next.js-focused), Fly.io / Render / Railway (newer crowd that filled the post-Heroku free-tier gap), Cloudflare Pages, Salesforce Platform, and the AWS/GCP/Azure managed-service families (App Runner, Cloud Run, App Service, etc.).
In 2026, the first choice for personal use is Fly.io / Render / Railway. For a commercial startup, Vercel (frontend) + Cloud Run / App Runner (backend) is the combo.
Default new apps to PaaS. Going down to IaaS is allowed only when “why PaaS doesn’t work” can be answered in 1 minute. Legitimate reasons: special kernel modules required, GPU instances required, direct integration with existing VPC (Virtual Private Cloud — logically isolated private network in cloud) resources, compliance requiring auditable OS images. Outside those, PaaS is safer. “IaaS just feels cheaper” ignores the fact that operational labor cost makes a $300/month IaaS effectively $3,000/month in real terms.
IaaS
IaaS rents virtual servers over the Internet. AWS EC2, Google Compute Engine, Azure Virtual Machines. The most straightforward form: “rent a server monthly.”
Until AWS EC2’s 2006 launch, “server” meant on-prem (physical machine, power, network — capital expenditure of thousands of dollars and weeks of lead time). EC2 changed that to “minutes and a credit card.” Airbnb, Dropbox, and Slack are all children of the EC2 era — without that shift, most “unicorns” wouldn’t exist.
| Pros | Cons |
|---|---|
| High freedom (anything possible) | Specialty knowledge required |
| Cheaper than on-prem | OS / middleware management on you |
| No hardware to buy | Security is your job |
| Easy BCP setup | Cost can exceed PaaS |
Since Heroku in 2007, “PaaS is even easier” spread, and demand drifted toward higher abstraction. Docker (2013 — packaging app + runtime into a lightweight container) and Kubernetes (2015 — container orchestration) further reduced the necessity of bare IaaS. Today, picking pure IaaS is reserved for compliance constraints or special requirements PaaS can’t meet. “Educational” is a soft choice — what you should learn on work hours is the app’s value, not how to apply OS patches.
FaaS
FaaS runs a single function only when called. AWS Lambda (launched 2014), Google Cloud Functions, Azure Functions, Cloudflare Workers — pure pay-as-you-go, $0 when idle. “Serverless” as a term landed via this model.
FaaS’s substance is the redefinition of infrastructure from “always running” to “runs only when called.” Traditional servers charged whenever they were on, even at zero traffic. FaaS bills only on “execution time × memory × request count,” so a job hit a few times a month costs effectively zero.
Nightly batch, Webhook (HTTP callback fired on external-service events) handlers, admin APIs, image-thumbnail generation — for these intermittent workloads, FaaS dominates.
| Pros | Cons |
|---|---|
| Implementation without environment concerns | Less customization |
| Pay-as-you-go (cheap) | Cold starts (first-call latency) |
| Auto-scaling, infinite parallelism | Hard to debug |
| Quick to ship | Limited execution time (minutes) |
Running an always-on web server on FaaS is a textbook bad fit. When traffic pauses the container is destroyed, and the next request needs to recreate it — the cold start problem. Node.js: 100-500 ms penalty per cold start. JVM-class: 2-5 seconds. This degrades UX consistently — users don’t distinguish “system is slow” from “my connection is slow.” For always-on APIs, just pick PaaS or container services. Don’t use FaaS for always-on APIs — that’s the classic early landmine.
Hybrid applications
Hybrid apps wrap a Web-tech (HTML/CSS/JS) implementation in a native shell for distribution. Mostly used for mobile, where covering iOS and Android with one codebase is the biggest weapon. For projects without the budget to hire separate teams per OS, hybrid is the de facto standard.
Two lineages:
- WebView-style (Cordova, Ionic): embed a browser inside the native app to render Web pages. Easier to implement; behaves like a browser, often heavy.
- Native-rendered (React Native, Flutter): code in JS or Dart, mapped to native UI components. Lighter, closer to native UX. The 2026 default.
Traits:
- OS-independent (the main feature)
- Easier hiring (Web engineers can do it)
- Tends to feel heavier than native
- Can feel browser-like in interactions
Major examples: React Native (Meta), Flutter (Google), Ionic, Electron (desktop). Flutter and React Native are the default for projects that can’t afford separate iOS/Android teams. A mixed model where critical screens stay native and the rest goes hybrid is also common (Instagram and Discord both run React Native + some native).
The known landmine in hybrid: deep native-feature access. Bluetooth fine-control, camera depth sensors, push-notification details — hybrid plugins often lag behind native API updates and break suddenly. Most “app crashes after OS update” stories trace back to plugins. iOS/Android dual-support starts from hybrid; pick native only when you can immediately answer “why hybrid won’t do.”
Web vs Native deciders
| Aspect | Web | Native |
|---|---|---|
| Distribution / updates | Open URL | App store |
| Cross-platform | Excellent | Poor (re-implement) |
| Performance | Mid to high | Highest |
| Direct hardware control | Limited | Full |
| Offline | Limited (PWA) | Excellent |
| Initial start | Slow | Fast (already installed) |
If any one of “0.1s latency is fatal,” “direct hardware control,” or “offline mandatory” is non-negotiable, pick native. Otherwise, Web. Games, video editing, CAD, medical-device UIs, and trading terminals fall on the native side. Look at how peers in your industry built it — copying the market’s revealed preference is faster than reasoning from first principles.
PWA (Progressive Web Apps) achieves “near-native” but iOS still imposes restrictions. For full features, go to hybrid or native.
Selection by case
| Case | Recommended |
|---|---|
| Service independent of user/device/location | Web (SaaS) as default |
| Business where 0.1s latency is fatal | Native (PC software) |
| Smartphone-first service | Mobile app or Hybrid |
| Special-purpose terminals (kiosks, vending machines, navigation) | Native / embedded |
| Bulk batch processing of large data | Native (batch) |
| Building a developer platform | Major clouds dominate; new entry not recommended |
For internal business systems, Web is the only reasonable choice. Games and video editing have no realistic non-native alternative — Google Stadia’s 2019-2023 wind-down was the symbol of that wall.
By phase
| Phase | MAU range | Recommended | Decision axis |
|---|---|---|---|
| MVP / validation | < 1k | Web (SaaS + Edge/Serverless) | Zero distribution friction, daily deploys |
| Early growth | 1k-100k | Web (SaaS + CDN + managed DB) | Let the cloud scale, focus on code |
| Scale | 100k-1M | Web + hybrid mobile as needed | Decide on native by CV rate (consider native if browser CV drops below 30%) |
| Enterprise | 1M+ | Web + native + embedded as needed | Allow multiple forms for performance / compliance |
Picking Electron / React Native / Flutter at the MVP stage is usually overkill. Build a Web app first, gather actual usage data (“70% of users come from mobile,” “70% of repeat use is offline”), and convert to native afterwards. The reverse order burns the validation phase on store reviews. The decision point during scale is conversion rate (CV) through browser dropping below 30%; native investment pays off only after that.
Form-migration traps
Changing form mid-stream is essentially a rebuild. Common traps:
| Forbidden move | Why |
|---|---|
| ”Port Web to native as-is” | DOM-assumed UI degrades both performance and UX in native; UI rewrite is mandatory |
| Decide native -> Web right before release | iOS/Android behavior differences and offline assumptions can’t reproduce in Web in time |
| Adopting Electron/RN/Flutter just because “both OSes covered” | Plugins can’t keep up on deep native features (Bluetooth, camera depth, push details) |
| Migrating an always-on API to FaaS | Cold starts shave UX every time — Edge Runtime or containers are the answer |
| Distributing hybrid without store review | iOS Enterprise distribution still has signing/review constraints; check TestFlight/MDM assumptions first |
Iron rule of form migration: “run both forms in parallel for 3-6 months.” Killing the old form while building the new one removes the rollback path — a textbook landmine. Issues always surface right after the new launch, and a live old form gives you a fail-back option. Cutting the old over too early turns into a total outage.
The other rule: scope down the migration. “Big-bang” full migration almost always fails outside very small projects. Use the Strangler pattern (gradually replace and eventually retire the old system) — design assuming both old and new run together for a period.
Don’t start a form migration without securing a parallel-running window. Migration without a retreat path is gambling, not design.
The AI-era lens
With AI-driven development (vibe coding — writing code by describing requirements to AI in natural language), the selection axis has shifted from “human learning cost” to “AI’s fluency.” AI’s generation accuracy scales with the quantity and quality of training data. Web has the largest training-data pool and the highest generation accuracy. The drift of new projects to Web will only intensify.
| AI-era favorable | AI-era unfavorable |
|---|---|
| Web apps (information density, standard tech) | OS-specific native (info dispersed) |
| React Native / Flutter hybrids (one code, multiple OSes) | Separate iOS/Android (duplication cost unchanged with AI) |
| IaaS + container + IaC (config as code) | GUI-required PaaS, custom consoles |
| FaaS (just write code) / Wasm (WebAssembly — fast portable bytecode) | Custom complex runtimes |
The common trait of AI-era favorable tech: “complete in code.” AI can read and write code; GUI clicks and proprietary consoles stay outside AI’s reach. IaC rose in relative value for this reason — what was “overkill to write everything in Terraform” before AI is now “overkill not to.”
That said, physical limits (latency, hardware, offline) don’t budge with AI. Asking AI “make latency 10ms” doesn’t beat the speed of light. The new axis is the intersection of “AI can write it easily” and “the requirement is met.” GUI dependence and proprietary consoles are heavy AI-era shackles.
AI-era trend — backend-minimized stacks
In the late 2020s, with AI lifting individual developers, “rich frontend, ruthlessly minimal backend” took hold. Combine an idle-zero function-execution environment with a CDN (Content Delivery Network) -served frontend; no always-on server. Personal projects can run production for a few dollars a month or in free tiers. The barrier to entry has dropped to historic lows — comparable to the 1990s “personal site on a home server” era for individual builders.
But “backend-minimized = FaaS only” isn’t accurate. The pattern has split three ways: FaaS (function execution on call), Edge Runtime (lightweight runtime at CDN edge), BaaS (Backend as a Service — auth, DB, functions all in one vendor). All three share idle-zero billing but differ on LLM streaming compatibility and lock-in depth.
| Pattern | Examples | Strengths | Weaknesses |
|---|---|---|---|
| FaaS | AWS Lambda | Rich info, exists on every cloud | Cold starts, 15-min timeout |
| Edge Runtime | Cloudflare Workers, Vercel Edge | Near-zero cold start, streaming | Partial Node compatibility, heavy compute weak |
| BaaS | Supabase, Firebase, Convex | Auth + DB + functions bundled | Strong lock-in (Firebase/Convex), pricing cliffs |
LLM (Large Language Model) streaming popularity flipped Edge Runtime into the lead. Generative-AI responses arrive as tokens over many seconds, requiring connection-held streaming to the client. Pure FaaS hits cold-start and max-execution-time limits for this; it has retreated toward async batch.
BaaS lock-in differs by product. Firebase and Convex depend deeply on proprietary APIs and data models — escaping is essentially a rewrite. Supabase is open-source-stack (Postgres + PostgREST + GoTrue), self-hostable, and standard SQL — exit cost is comparatively light. “All BaaS is locked in” is too crude; Supabase is “BaaS with an exit.” Estimate “how many days to migrate if the vendor stops” before adopting.
For new projects with LLM streaming, Edge Runtime is the first candidate. FaaS lives in batch and webhook territory.
”Picked IaaS to learn” — a weekend (industry case)
A standard rite of passage: starting a small SaaS as a side project, picking AWS EC2 because “it’ll be educational,” burning the weekend on nginx, systemd (Linux’s daemon manager), domain setup, manually starting PostgreSQL, writing the Let’s Encrypt (free SSL) renewal cron, and finally getting Hello, World on the Internet — completely exhausted.
At that exact moment, Heroku was doing the same thing in git push heroku main on its free tier. (Heroku’s free tier was retired in November 2022; Fly.io / Render / Railway now play that role.) For personal projects, “if you can’t write the reason not to use PaaS, use PaaS” is the only sane judgment. People who’ve touched both swear by it.
“Educational” and “product development” are different things. Learn infra outside work hours; ship products on PaaS. Mixing them evaporates time meant for the product. You don’t get that time back. The void after burning two days, then deploying on Heroku in 30 minutes, is the kind of feeling you only need to experience once.
“It’ll be educational” is the most expensive selection rationale. Bring it into a real project, and someone’s time melts.
What you must decide — what’s your project’s answer?
Articulate your project’s answer in 1-2 sentences for each item.
- Application form (Native / Web / Hybrid)
- Web service model (SaaS / PaaS / IaaS / FaaS)
- Target platforms (Windows / Mac / iOS / Android / Linux)
- Offline requirements
- Performance targets (latency, throughput)
- Distribution / update frequency and method
- Initial cost and operating cost ceilings
These belong to project week 1. Postponing means downstream choices proceed on tentative assumptions, and major rework hits when the form is finally locked.
Common failure patterns
- Picking SaaS just because it’s trendy — Forcing native-fitting work into the Web and dropping reputation on performance. Casual webification of video editing, 3D modeling, or large-data work hits browser limits (memory ceilings, tab crashes).
- Native iOS / Native Android separately — 2x effort, 2x bugs. Hybrid was enough for many of these. Separate native is justified only for “1ms-fatal” domains (gaming, finance) and large companies with established native teams.
- FaaS for always-on APIs — Cold starts shave UX. Always-on goes to PaaS. Past tens of thousands of requests/day, FaaS often loses to Cloud Run or ECS Fargate on total cost.
- “Educational” IaaS — OS patches, certificate renewal, log rotation — all “educational.” Meanwhile the actual app moves zero millimeters. Starting on PaaS gets you to first launch 2 weeks earlier.
How to make the final call
Form cannot change later. Start by deciding “the single highest priority” and cleanly removing forms that can’t satisfy it.
Eliminate candidates that can’t satisfy physical requirements (latency, hardware control, offline), then match what remains against user demographics and dev/ops resources. Get this order wrong and a reversal will hit later.
The AI-era axis adds another lens: when two forms can satisfy the same requirements, pick the one that completes in code (Web / containers / IaC). GUI operations and custom-console dependencies stay outside AI’s reach and keep the learning cost on humans permanently. Marginal in the early 2020s, this is a first-class decision axis under AI-driven development.
Selection priority:
- Filter candidates by physical requirements (eliminate forms that can’t satisfy them).
- Decide the category by reach (worldwide browsers vs specific devices).
- Land on the realistic answer by dev resources (people, budget, skill).
- Use AI compatibility as the final differentiator.
“Just go with what’s trendy” is the most expensive selection. Form is also a statement of where you’re betting your differentiation. When in doubt, build it on the Web. Pick native only when you can write the reason on the spot.
Summary
This article covered the application form decision that comes first in system architecture.
When in doubt, Web. If the reason for native can’t be written on the spot, start with Web. Form is the most upstream irreversible decision; it deserves discussion until you can articulate it in week 1.
The next article covers the deployment model (on-prem / cloud / hybrid).
Back to series TOC -> ‘Architecture Crash Course for the Generative-AI Era’: How to Read This Book
I hope you’ll read the next article as well.
📚 Series: Architecture Crash Course for the Generative-AI Era (6/89)