Skip to main content
Technology Blog

Choosing Between REST and GraphQL for a Business Application

a monitor showing source code with a developer seated at it

The question arrives as a performance complaint

It usually starts the same way. A product team opens a ticket saying the API is slow, and the evidence in the ticket is a screenshot of a mobile screen that took four seconds to populate. Somebody has already read that as a database problem and is talking about indexes.

office buildings and towers photographed against an open sky

Look at the network trace instead and the shape of the problem becomes obvious. Six or seven requests went out over the same connection, several of them to fetch a list, and each one returned a full collection with fields the app never displayed. The user waited not because one query was slow but because the client needed five round trips, in sequence, before it could paint anything.

That is the situation GraphQL was designed to address, and the reason it became fashionable so quickly. The harder question — which of the two approaches should this project use — is answered differently, because the decision is not really about the API style at all. It is about who consumes the API, how many consumers there will be, and whether the shape of the data is still moving.

What each approach actually is

REST is a set of conventions over HTTP. Resources have identifiers, they are addressed by URLs, and the HTTP method expresses the intent of the request. The server decides what a resource looks like, and every consumer receives all of it. That last point is the one people forget: a REST response shape is a server-side decision that every client has to live with.

a smartphone held in one hand with an app open on the screen

GraphQL inverts it. There is one endpoint. The client sends a document describing the fields it wants, the server executes it against a schema, and the response contains exactly those fields. Adding a field to a query does not require changing the server. That property — independent evolution of clients and server — is the real argument for it, and it is a strong one in the specific circumstances where it holds.

The consequence follows from that. Because the query is written at request time, most of what a REST API gets for free has to be built explicitly: caching, request limits, authorisation per field, and a way to know what is expensive before you run it. None of that is impossible in GraphQL. All of it is code you have to write, and that work does not appear in the “just move to GraphQL” estimate.

The cases where REST is the right answer

Most projects should still start here, and it is worth being blunt about why rather than assuming a technical preference.

office buildings and towers photographed against an open sky

One client, or clients you control

GraphQL’s main advantage is decoupling consumers you do not control — a mobile app, a partner integration, several front ends maintained by different teams with different release cycles. If there is one web front end that your team ships together with the server, that advantage is largely theoretical. You control both sides, so you can change the response shape and deploy the change immediately. REST gives you the same result with less machinery.

The data is a hierarchy, not a graph

GraphQL’s data model suits objects that reference each other: an order with a customer who has an address; a post with an author who has posts. If your domain is mostly rows in tables that are looked up by identifier — invoices, line items, bookings — then a conventional endpoint per resource is a natural fit, and a single join in a SQL statement does the work that a resolver graph would otherwise do client-side.

You need caching at the edge

This is the practical point that decides more projects than any other. A REST endpoint with sensible cache headers is trivially cacheable by a CDN or a reverse proxy. A GraphQL endpoint is cacheable, but the cache key has to account for the query document and the variables, which in practice means a normalised key, careful header handling, and explicit decisions about whether a given query may be cached at all. If a large share of your traffic is public, readable content, REST’s position is strong.

Public and third-party consumption

Anything that needs to be documented, supported and kept stable for consumers outside your organisation is cheaper to expose as REST. The tooling for it is mature, the mental model is universal, and a new integrator does not need to learn a query language before they can make their first call. A GraphQL API behind a public product is a documentation project with a schema instead of a list of endpoints.

Where GraphQL earns its cost

The opposite cases are real, and when they apply the flexibility is not a nicety — it is what makes the product maintainable.

Many clients with different needs. A web application, an admin tool, a partner dashboard and two mobile apps, all needing overlapping but non-identical data. With REST, every distinct shape of need either becomes its own endpoint or becomes a query-parameter soup that every client and the server both have to understand. The endpoint count grows faster than the number of use cases.

Data that is still moving. During the first year of a product, the entity list changes often. In REST, a client that needs a new field has to wait for a server deployment, then be redeployed. In GraphQL, the client can ask for the field as soon as the server exposes it. For a product team shipping weekly, that removes a real class of coordination cost.

Object-shaped screens. A page that is fundamentally a composition of related objects — a dashboard assembled from five entity types — maps naturally onto one query. With REST it is either five requests and a client-side merge, or a bespoke aggregation endpoint that you now have to maintain and version separately.

Note the pattern in all three: the payoff scales with the number of independent consumers and with how uncertain the schema is. Both are low in a new internal tool with one user interface. That is not an argument against GraphQL; it is an argument for recognising that you are being asked to pay setup cost now for a benefit that arrives later, if it arrives.

What GraphQL costs that nobody mentions at the start

Honesty here saves more time than it costs.

a laptop open on a desk beside a notebook, a phone and a cup of coffee

Authorisation gets harder. In REST, protecting a resource is mostly a matter of checking who the caller is and whether they may have that resource. In GraphQL, a single query can touch several types at different depths, so authorisation has to be checked per resolver, and a field added in a hurry can quietly bypass it. Data that a caller must never see becomes a per-field concern across the whole schema.

You must build the guardrails REST gets from HTTP. Query depth limits, cost analysis, complexity limits, timeouts, persisted queries, rate limiting per operation rather than per request. A query nested five levels deep with fan-out at each level can do serious work in a single request, and HTTP status codes do not describe it well. Without analysis in front of execution you get an outage caused by one client query rather than by a flood of requests.

Error handling is less crisp. HTTP has a status code, and everyone downstream understands what a 404 or a 422 means. GraphQL conventionally returns 200 with an errors array, which breaks logging, monitoring, retry logic and caching assumptions throughout the infrastructure. Teams that deploy behind an existing platform usually spend real effort on this.

Server-side resource use moves from the client to the server. With REST, a heavy call is a heavy call and it fails in an obvious place. With GraphQL, the client can compose several expensive calls into one request that looks cheap. The tuning work does not disappear; it moves, and it needs somewhere to live.

None of this is an argument against the approach. It is an argument for a team that knows it is choosing it, and that has budgeted for the layer between the API and the database rather than treating it as a library. At SmartEdge IT Solutions that layer is treated as a deliverable in its own right, because it is the part that decides what is expensive, what is allowed and what a caller is permitted to see. Our API integration work usually ends up owning exactly this part.

The guardrails that have to exist before public traffic arrives are worth listing, because teams routinely ship without them:

  • A depth limit, so a query cannot nest indefinitely through self-referencing relationships.
  • Cost analysis, so a query with heavy fan-out is recognised before it runs rather than after.
  • A hard timeout on execution, applied server-side rather than left to the client.
  • Rate limiting per operation, which is not the same as per request once queries differ in cost.
  • Persisted or allow-listed queries for anything unauthenticated, so arbitrary documents are not executed on demand.

How the decision usually goes in practice

When we are asked to settle this for a client, we work through a short set of questions, and the answer is frequently neither of the two headline options.

industrial plant equipment and power infrastructure
  1. How many independent consumers will this API have, and can you deploy them all at once?
  2. Is the entity model still changing, or has the product stabilised?
  3. What share of the traffic is public, cacheable content?
  4. Does any screen need data from several entity types at once in a single view?
  5. Is there an internal or third-party audience that needs a stable, documented surface?
  6. What is the team’s existing operational experience with the surrounding platform?

Those answers frequently point somewhere else entirely, which is the honest third option: REST at the boundary, with a purpose-built aggregation layer behind it for the screens that need it. A handful of carefully designed endpoints, each returning a composed view, gives most of the benefit for a fraction of the ongoing cost. It scales down gracefully, it stays cacheable, and it does not require the client team to learn a query language. What it costs you is that each composed endpoint has to be maintained deliberately rather than emerging from the schema — so when the composition changes, somebody has to change it.

Running both, badly, is the common outcome

Most systems that hurt are not a clean choice. They are GraphQL added in front of a REST API that still exists, with both serving overlapping data, and two divergent ideas of what the data means. The frontend team uses the new endpoint, a partner integration uses the old one, and a field gets updated in the database but not in the REST representation, so two consumers of the same system disagree about the value of a single field.

a laptop showing a financial report beside a notebook, a calculator and a phone

The way to avoid this is a decision about ownership rather than about technology: one representation is authoritative for each entity, and anything else is derived from it. If both must be exposed publicly, make the second one a projection of the first and generate it, rather than letting a developer maintain both by hand.

Where a project is a Node application with a React front end, the practical detail that matters most is the data-fetching layer, because that is where the client-side decision about REST versus GraphQL is actually made, three times a day, by whoever writes the next screen. Setting that up deliberately as part of the build is covered in our Node.js development and MEAN stack development work, where the caching and error-handling decisions tend to get made once rather than per feature.

And if the decision is genuinely close, the honest answer is that it matters less than the surrounding questions. Whoever maintains the service, whether the operations team can see what it is doing, and whether the schema is documented well enough for a new developer to add a field without reading the source. Those decide whether the API becomes an asset or a liability over two years, whichever style you pick, and they are the questions SmartEdge IT Solutions would rather settle before the first endpoint is written than eighteen months afterwards.

Editorial profile

Amelia Brooks Mobile and Product Editor

Amelia Brooks writes about mobile apps and the products that sit on a phone for SmartEdge IT Solutions: native against cross-platform, store submission, release management, and the handover notes that let somebody else pick the work up.

Also 2 articles in the Insights archive.

← Back to Blog