Every enterprise application is really three things stacked on top of each other:
- A database that models the world.
- An API that mediates access to the model.
- A UI (or several — web, mobile, integrations) that lets humans and systems work with the model.
The order you design these three in shapes everything else: performance ceiling, integration story, refactor cost, team topology. And the reflex answer — “UI first, that’s what the customer sees” — is wrong more often than it’s right.
Here’s the version of this conversation that actually helps.
The three sequences
UI-first
Draw wireframes. Prototype in Figma. Build the frontend against mocks. Design the API to serve the UI. Design the database to serve the API.
When it works: consumer-facing products where the UX is the whole thing. Instagram, Notion, Linear. The UI is the product — designing anything else first would be inside-out.
When it fails: enterprise apps where the model is the actual value. If your app is a customer database, an inventory system, or an approval workflow — the schema is what the business is. Retrofitting a model to a UI wireframe gives you an app that looks nice for six months and a data migration in year two.
API-first
Design the API contract before writing implementations. OpenAPI or GraphQL SDL as the source of truth. Backend and frontend teams work in parallel against the contract. Database is designed to serve the contract.
When it works: systems with multiple consumers (web + mobile + partner integrations), or systems where the API is the product (Twilio, Stripe). Also: any team with a strict frontend/backend split and needs to parallelise.
When it fails: when the team assumes the API contract is enough documentation, and no one thinks about the data model until the app hits a scale issue in production.
Database-first (model-first)
Domain modelling first. Get the entities, relationships and invariants right. The API is a projection of the model. The UI is a view over the API.
When it works: enterprise apps where the domain is complex — finance, healthcare, logistics, HR. The domain model is the durable asset. UIs and APIs come and go; the model persists across a decade of refactors.
When it fails: when the team over-engineers the model before knowing the actual product shape. You need enough product clarity to model correctly — not much, but not zero.
What we actually do — and why
Our default for enterprise projects, in this order:
-
Domain sketch (2–5 days). Whiteboard the entities and relationships. Write them as sentences: “an Order has one Customer, many LineItems; a LineItem has one Product and one Quantity.” No SQL yet. No ORM. No columns. Just concepts and how they connect. This is where a good functional consultant is worth their fee.
-
API contract sketch (3–7 days). Design the API against those entities — resources, actions, invariants. Prefer REST for CRUD-heavy models, GraphQL for read-heavy multi-consumer patterns, JSON-RPC for tight action-verbs. Write it as OpenAPI or SDL. Include the “boring” endpoints — list, filter, sort, paginate. Enterprise apps live and die on these.
-
UI wireframes (parallel to step 2). Yes, wireframes come after the domain sketch. But they can start once the domain sketch is stable, and they run in parallel with API design. The UI designer and the API designer should talk daily during this phase.
-
Database schema (finalised after step 2). Now translate the domain into a schema. Indexes, constraints, foreign keys. The concrete details that were premature two weeks earlier are exactly right now.
-
Backend implementation + frontend implementation (in parallel, against the contract).
-
Integration + polish.
Total pre-implementation: 2–3 weeks for a mid-sized app. That feels expensive to teams that want to start writing code. It’s the cheapest 2–3 weeks the project will ever spend.
The API design decisions that matter most
Skip the REST-vs-GraphQL religion war. The decisions that actually predict success:
1. Consistency of resource shape
The same resource returned from /orders/{id} should be the same shape as the one returned from /customers/{id}/orders. Consumers hate having to reshape data based on which endpoint returned it.
2. Explicit pagination, filtering, sorting, sparse fieldsets
Do this on day one for every list endpoint. Cursor-based pagination when possible, offset when you must. Standard query-string shape. Document it once and follow it everywhere. Retrofitting is painful.
3. Idempotency for writes
Every POST that creates or mutates should accept an Idempotency-Key header. This is the single biggest reliability improvement you can build in from day one. Any modern payment API does this; every enterprise API should too.
4. Versioning strategy — pick one before you ship
- URI versioning (
/v1/orders,/v2/orders) — most explicit, easiest to reason about, easiest to route. - Header versioning — cleaner URIs, harder to spot in server logs.
- No versioning (evolve in place) — works if you’re extremely disciplined and have few external consumers. Otherwise it’s a slow-motion disaster.
We default to URI versioning for anything that will be consumed by more than the current team. Don’t design cleverness where boring works.
5. Errors as first-class citizens
Error responses need a stable shape (RFC 7807 / Problem Details is a fine default). Every error should carry a machine-readable type code that frontend and integrations can switch on. Don’t return 500 Internal Server Error for a validation failure and expect anyone to build a good UX on top of that.
6. Auth and rate-limit design before the first endpoint
Decide token flow (OAuth 2.1 flows, session cookies, mTLS for service-to-service) before you write endpoint one. Retrofitting auth into a working system is expensive and often introduces vulnerabilities.
REST or GraphQL — the honest short answer
- REST when: writes are as important as reads, resources are well-defined, consumers are diverse (mobile / web / partners / internal), and you want HTTP semantics (caching, ETags, conditional requests) to work.
- GraphQL when: reads are dominant, screens compose multiple entities into single views, and you have discipline around N+1 avoidance, query complexity limits, and persisted queries.
If your team is currently arguing “REST vs GraphQL” and doesn’t have strong opinions about persisted queries, complexity budgets, and DataLoader-style N+1 avoidance — pick REST. GraphQL rewards teams that know what they’re doing with it and punishes teams that don’t.
For everything Parth Infotech has shipped in the last three years, the ratio is 9 REST : 1 GraphQL. The one GraphQL project had a clear justification (three different frontends composing 12 different entity types per screen). Everything else was better off with REST.
The three-way trap
There’s a specific failure mode we see over and over: teams design UI and database in parallel, and let the API “emerge” between them. What you get is:
- An API that leaks database shape (SQL joins showing up as endpoint parameters).
- Frontends that couple to database structure through the API.
- A refactor cost of 10x on any schema change, because the change has to ripple through the API contract and every frontend at once.
The fix is to explicitly design the API contract as its own artefact, with its own owner, its own review process. Not the frontend team’s second job. Not the backend team’s afterthought. A proper interface.
When to break these rules
- Very small internal tools — skip the ceremony. Rails scaffold, Django admin, Retool — they exist for a reason. Don’t build a 4-week API scaffolding phase for a form that saves to a spreadsheet.
- Prototypes — go UI-first. The point is to learn what to build, not to build well.
- Product-market-fit exploration — go UI-first, throw it away in year one if it works, rebuild properly in year two.
- Systems with a single team and a single frontend forever — you can get away with a lot of skipped API discipline, but budget the tech debt honestly.
The single question that predicts everything
Ask this in scoping:
“In three years, will this system have more than one consumer of its data?”
If yes — API-first is not optional. Design the contract with the same discipline you’d design a database schema.
If no — you have latitude. UI-first is often fine. But even then, having a clean API layer will save you when you inevitably do add a second consumer (a mobile app, a partner integration, an internal admin panel).
What we hand to teams starting an enterprise project
Three artefacts, in this order:
- Domain model diagram — entities, relationships, invariants. One page. Reviewed by product + business + engineering.
- API contract (OpenAPI / SDL) — every endpoint, every schema. Living document. Reviewed weekly during the design phase, then locked before implementation.
- UI flow diagram — high-level screen flow, not pixel wireframes. Pixel wireframes come later.
If you don’t have these three, you don’t have an architecture yet. You have a hope.
Related: The solution architect’s checklist for enterprise projects covers how this fits into a bigger delivery structure.
If you’re at “we need to figure out the architecture before we start building,” talk to us — this is one of the calls we most enjoy.