Hire GraphQL developers
GraphQL lets clients ask for exactly the data they need, and hiring for it means testing whether someone has solved the performance and authorisation problems that creates.
What GraphQL actually is
GraphQL is a query language and runtime for APIs, originally from Meta and now governed by a foundation. Instead of a set of endpoints each returning a fixed shape, a GraphQL server exposes a typed schema and clients ask for precisely the fields they want in a single request. The response mirrors the query.
The problems it addresses are real. A client needing data from several REST endpoints makes several round trips, and an endpoint designed for one screen returns too much for another. GraphQL removes both, which matters most for mobile clients on slow connections and for front ends that evolve faster than the back end can produce new endpoints.
What it does not do is remove work; it relocates it. Flexibility given to the client becomes complexity on the server, because any combination of fields a client can request is a query the server must satisfy efficiently and authorise correctly. Teams that adopt it expecting simplification, rather than a different distribution of the same difficulty, are usually the ones that regret it.
The part that separates seniors from mid-levels
The N plus one problem is the defining performance issue, and it is structural rather than incidental. Resolvers run per field per object, so a query fetching a list and then a related field on each item naturally produces one query per item. The solution is batching, typically through a data loader that collects requests within a tick and issues one query. A candidate who does not mention this when asked about performance has not run GraphQL under real load.
Authorisation is the second area and the one that causes security problems. In REST, an endpoint is a natural place to put a permission check. In GraphQL there is one entry point and a graph the client traverses, so a field reachable by an unexpected path can leak data. Authorisation has to happen at the field or resolver level, consistently, and reasoning about what is reachable from where is genuinely harder than in an endpoint-based design.
The third is that clients can write expensive queries, deliberately or accidentally. A deeply nested query, or one requesting a large list with nested relations, can be far more costly than anything a REST endpoint would permit. Production servers need query depth limits, complexity analysis, and frequently persisted queries so that only known operations are allowed. Without these, the API's flexibility is also its denial-of-service surface.
Where GraphQL is used
The label “GraphQL developer” covers several jobs that share a technology and little else. These are the settings the work usually turns up in, and the one you are hiring into should shape the whole process, because the judgement each demands is different.
Mobile back ends
Where round trips are expensive and over-fetching costs the user data and battery, which is GraphQL's strongest case.
Aggregation layers
A single API in front of several internal services, presenting one coherent graph to clients.
Multi-client products
Web, mobile and partner clients with different data needs served from one schema.
Content delivery
Headless content management systems, where GraphQL has become a common query interface.
Commerce storefronts
Product and catalogue queries where clients need varying shapes of the same underlying data.
Internal platform APIs
Federated graphs across an organisation, which is a substantial engineering commitment in its own right.
If a candidate's experience sits in a different row of that list from the work you have, that is not a reason to reject them, but it is the thing to probe. Ask what would be different about their approach in your setting. Someone who can answer that has transferable judgement. Someone who says it would be much the same has probably not thought about it.
Support status of the tools in this stack
GraphQL is a specification rather than a product, so what matters is the maturity of the server implementation and client tooling a team uses rather than a version of the language itself.
GraphQL itself is not versioned as a single product, so the useful equivalent is the support status of the tools a GraphQL developer works with daily. The table is read from public release data rather than written by hand, so it states what is supported now. It is worth having in front of you during an interview: asking which of these a candidate has upgraded, and what broke, gets you further than asking how many years they have used each.
| Tool | Latest release | Release date | Maintained lines | Furthest end-of-life date |
|---|---|---|---|---|
| Node.js | 26.10.0 | 2026-09-22 | 6 | 2029-04-30 |
| React | 19.3.0 | 2026-09-09 | none published | none published |
| PostgreSQL | 18.6 | 2026-08-11 | 5 | 2030-11-14 |
| Redis | 8.10.2 | 2026-09-17 | 5 | 2030-09-01 |
| Kubernetes | 1.37.1 | 2026-09-23 | 4 | 2027-10-28 |
| Next.js | 16.3.6 | 2026-09-22 | 1 | 2026-10-21 |
Source: endoflife.date public release data, read 2026-09-25. A tool with no published end-of-life dates sets its support boundary by ecosystem practice rather than by policy.
The practical use of this is in judging an estate rather than a person. A team running several of these past their support dates is usually not behind by accident; it is behind because upgrades were never anyone's job. That is worth knowing before you hire, because it tells you whether the first six months will be building new things or paying down what was deferred.
The toolchain around it
Nobody hires for GraphQL alone. The surrounding tools are where most of the day-to-day work happens, and a gap in any of them costs more time than a gap in the core library. This is the set that turns up most often on real job specifications alongside it.
- A schema-first workflow
- The schema as the contract between teams, versioned and reviewed.
- Apollo Server, GraphQL Yoga or a language equivalent
- The server implementation.
- DataLoader or equivalent batching
- The standard answer to the N plus one problem. Effectively mandatory.
- Apollo Client, urql or Relay
- Client-side caching and query management.
- Code generation
- Types generated from the schema for both client and server, which is much of the practical benefit.
- Query depth and complexity limits
- Protection against expensive queries, required in any public-facing deployment.
- Persisted queries
- Allowing only known operations, which also improves caching and reduces payload size.
- Tracing per resolver
- Field-level performance visibility, since a slow query can be one slow field.
Related skills that frequently appear on the same specification: Node.js, React, Next.js, TypeScript, React Native.
What to test in an interview
These are the topics that separate candidates in practice. Each one is given with why it discriminates, what a strong answer sounds like, and the response that should make you slow down. None of them requires a whiteboard.
The N plus one problem
The defining performance characteristic. Anyone who has run GraphQL seriously has met it.
- Strong answer: Explains why resolvers produce it, uses batching, and can describe finding a case in production.
- Warning sign: Has not encountered it, which means they have not run it at any real scale.
Authorisation design
Where GraphQL creates genuine security risk relative to REST.
- Strong answer: Checks at the resolver or field level, reasons about reachability through the graph, and does not rely on the client requesting only permitted fields.
- Warning sign: Authorises at the query entry point only, or assumes the schema restricts access.
Protecting against expensive queries
An API that lets clients compose queries needs limits.
- Strong answer: Applies depth and complexity limits, uses persisted queries where appropriate, and has considered the abuse case.
- Warning sign: Exposes a public endpoint with no limits at all.
Error handling
GraphQL returns partial data with errors, which clients frequently mishandle.
- Strong answer: Distinguishes partial failure from total failure, and designs errors the client can act on.
- Warning sign: Treats any response with an errors array as a total failure, or ignores it.
Caching
GraphQL loses the HTTP caching that REST gets free, and this surprises people.
- Strong answer: Understands that a single POST endpoint defeats HTTP caching, and uses client-side normalised caching or persisted queries.
- Warning sign: Assumes caching works as it does with REST.
Schema design and evolution
The schema is a long-lived contract.
- Strong answer: Designs around client needs rather than database tables, deprecates fields rather than removing them, and avoids versioning the whole API.
- Warning sign: Mirrors database tables directly into the schema.
When REST would be better
Tests judgement rather than advocacy.
- Strong answer: Can name cases where REST is simpler and sufficient, particularly single-client internal APIs.
- Warning sign: Treats GraphQL as universally superior.
Warning signs in a GraphQL codebase
The fastest way to read a candidate is to ask what they have found wrong in code they inherited. These are the patterns that come up most often, what they cost, and what fixing them looks like. A developer who recognises three or four of these from their own experience is worth more than one who can recite the documentation.
No batching
- What you see: Resolvers issuing a database query per item in a list.
- What it costs: Hundreds of queries for one request, with cost scaling by result size.
- The fix: Use a data loader to batch and deduplicate within a request. This is the standard solution and should be present from the start.
Authorisation at the entry point only
- What you see: A single check when the query arrives, with none at field level.
- What it costs: Data reachable through an unexpected path in the graph, which is a real and repeatedly demonstrated leak class.
- The fix: Authorise in resolvers, consistently. Test reachability rather than assuming the schema constrains it.
Unlimited query complexity
- What you see: A public endpoint accepting arbitrarily deep or broad queries.
- What it costs: A single crafted query can exhaust the server, which is a denial-of-service surface the API created.
- The fix: Apply depth and complexity limits. For clients you control, persisted queries remove the problem entirely.
Schema mirroring the database
- What you see: Types and fields matching tables and columns one to one.
- What it costs: The API becomes coupled to the storage model, and clients depend on internal structure.
- The fix: Design the schema around what clients need. The mapping to storage is the server's problem, not the contract.
Ignoring partial errors
- What you see: Clients treating every response containing errors as a total failure, or ignoring the field.
- What it costs: Either usable data discarded, or failures shown as success with missing fields.
- The fix: Handle partial responses explicitly and decide per field what a null means for the interface.
Adopting GraphQL for a single client
- What you see: A GraphQL layer serving one front end with stable data needs.
- What it costs: All the complexity of the approach with none of the flexibility benefit.
- The fix: Use REST. GraphQL earns its cost when several clients with differing needs consume the same data.
What each level can own
Job titles are not comparable between companies, so it is more useful to describe levels by what a person can be left to own without supervision. These are the boundaries we use when we assess a GraphQL developer.
- Junior
- Writes resolvers and queries in an existing schema. Needs review on batching and authorisation.
- Mid-level
- Owns a domain of the schema including its resolvers, batching and permissions. Can diagnose a slow query to the field.
- Senior
- Owns schema architecture, the authorisation model, performance and abuse protection, and the client caching strategy.
- Staff
- Owns the graph across teams, federation if used, schema governance and the decision about whether GraphQL remains justified.
How the work is usually scoped
Team shape follows the kind of work, not the headcount you happen to have budget for. These are the shapes that come up most often and the constraint that actually governs each one.
GraphQL layer over existing services
- Usual team: One to two developers.
- What governs it: Scoped by the number of backing services and by how consistent their data models are.
Schema design for a new product
- Usual team: One senior developer with client developers.
- What governs it: Designing around client needs requires the clients in the room. Doing it alone produces a schema shaped like the database.
Performance remediation
- Usual team: One senior developer, time-boxed.
- What governs it: Nearly always batching. Field-level tracing identifies it quickly.
Authorisation review
- Usual team: One senior developer.
- What governs it: Worth doing deliberately on any graph that grew without a consistent model.
Federation adoption
- Usual team: Two senior developers plus owning teams.
- What governs it: A substantial organisational commitment. Only justified with several teams owning parts of one graph.
Migration work you may actually be hiring for
A large share of GraphQL work is not new development. It is moving an existing system from one state to another while it stays in service. These are the migrations that come up most often, and each one asks for a different kind of experience from the person you hire.
REST to GraphQL
- Why teams do it: Several clients with differing data needs, or a front end constrained by endpoint shapes.
- What to watch: Run both in parallel and move clients gradually. Adding a GraphQL layer over existing REST services is the usual first step and it is also where the N plus one problem appears, so build batching in from the start.
Resolvers without batching to data loaders
- Why teams do it: The single largest performance improvement available on most GraphQL servers.
- What to watch: Loaders must be scoped per request, not shared globally, otherwise one user's data can be served to another from the cache. This is a genuine and serious mistake.
An ad hoc graph to a governed schema
- Why teams do it: A schema that grew without review becomes coupled to storage and hard to evolve.
- What to watch: Deprecate rather than remove, and give clients a migration window. Breaking a schema breaks every client at once, which is the thing GraphQL was supposed to avoid.
A single graph to federation
- Why teams do it: Several teams owning parts of one API without a shared codebase.
- What to watch: Substantial tooling and governance overhead. Only worth it with genuine organisational need, and the schema ownership boundaries should be settled before the technology is chosen.
Migration work rewards a different temperament from greenfield work. The useful question in an interview is not whether someone has done the specific migration you face, but whether they have ever run one incrementally: behind a flag, with both paths live, and with a way back. Developers who have only done big-bang cutovers tend to propose them again.
What a good brief for this role contains
Most of the time lost in hiring a GraphQL developer is lost before anyone is interviewed, in the gap between what the brief says and what the team actually needs. These are the points that, for this technology specifically, change who the right candidate is. A brief that answers them can be matched in days. One that does not produces a shortlist that looks reasonable and converts badly.
- How many clients consume the API and whether their data needs genuinely differ.
- Whether the server sits over a database directly or aggregates other services.
- Whether batching is in place, since its absence is the most common performance fault.
- How authorisation is currently handled, which is the main security concern.
- Whether the endpoint is public, because that determines how much abuse protection is needed.
- Whether federation is in use or under consideration, as that is a substantially larger commitment.
If you cannot answer some of these yet, that is normal and it is still worth writing down which ones are open. An unknown that is named can be worked around. An unknown that is papered over in a job specification turns into a rejected shortlist and a restart four weeks later.
What the US market pays for this work
GraphQL work is counted by the US Bureau of Labor Statistics under Software Developers. That classification is broader than the technology itself, so treat the figures as the shape of the market a GraphQL developer is hired into rather than as a rate card for the skill. Across the United States the Bureau counts 1,687,890 people in this occupation, with a median annual wage of $135,980.
The spread matters more than the midpoint. The 90th percentile is about 2.6 times the 10th, which is a wide band for a single occupation and tells you that the title on its own carries very little pricing information. Two people described as a GraphQL developer can sit at $82,460 and $214,670 in the same national dataset. When a budget is set from a median without asking which end of that range the work actually needs, the hire that follows is usually the wrong one in one direction or the other.
Related classifications are worth reading alongside it, because teams hiring for GraphQL frequently end up recruiting against these titles too:
| Occupation | Employed | 25th percentile | Median | 75th percentile | 90th percentile |
|---|---|---|---|---|---|
| Software Developers | 1,687,890 | $105,210 | $135,980 | $171,980 | $214,670 |
| Web Developers | 70,190 | $64,230 | $92,650 | $126,230 | $162,290 |
Source: BLS Occupational Employment and Wage Statistics, May 2025. Figures cover all US employers and are not FuturByte rates.
These are employer-side wage figures for people on a US payroll. They exclude employer taxes, benefits, recruitment cost and the months a seat sits empty, all of which are real and none of which appear in a salary line. The useful way to read the table is as the cost of the alternative you are comparing against, not as a number to match.
How US metro markets compare for this role
The same job is priced very differently across the country. Ranked by median annual wage for Software Developers, the gap between the highest and lowest of the 28 metro areas covered here is a factor of about 1.7. San Jose sits at the top with a median of $213,110; Pittsburgh sits at the bottom with $124,500. A budget built from a national median will be wrong in both of those markets, in opposite directions.
| Metro area | Employed | Median wage | vs US median | Location quotient |
|---|---|---|---|---|
| San Jose, CA | 87,350 | $213,110 | +57% | 7.09 |
| San Francisco, CA | 69,030 | $186,640 | +37% | 2.68 |
| Seattle, WA | 92,770 | $167,280 | +23% | 4.10 |
| New York, NY | 121,000 | $166,830 | +23% | 1.17 |
| Boston, MA | 42,310 | $166,090 | +22% | 1.44 |
| San Diego, CA | 20,610 | $163,270 | +20% | 1.23 |
| Los Angeles, CA | 55,540 | $160,920 | +18% | 0.82 |
| Portland, OR | 18,260 | $156,000 | +15% | 1.39 |
| Washington, D.C. | 69,060 | $154,930 | +14% | 2.03 |
| Baltimore, MD | 16,850 | $138,900 | +2% | 1.14 |
| Denver, CO | 27,010 | $137,610 | +1% | 1.55 |
| Charlotte, NC | 20,820 | $135,920 | 0% | 1.41 |
| Chicago, IL | 40,370 | $134,380 | -1% | 0.82 |
| Austin, TX | 31,960 | $134,120 | -1% | 2.28 |
| Dallas-Fort Worth, TX | 67,030 | $133,290 | -2% | 1.52 |
| Philadelphia, PA | 28,480 | $133,040 | -2% | 0.91 |
| Atlanta, GA | 36,300 | $132,960 | -2% | 1.16 |
| Raleigh, NC | 12,580 | $132,770 | -2% | 1.56 |
| Miami, FL | 18,900 | $132,650 | -2% | 0.62 |
| Phoenix, AZ | 29,380 | $131,750 | -3% | 1.14 |
| Minneapolis-St. Paul, MN | 27,410 | $130,920 | -4% | 1.29 |
| Detroit, MI | 24,870 | $130,760 | -4% | 1.20 |
| Tampa, FL | 14,230 | $130,450 | -4% | 0.91 |
| Orlando, FL | 13,440 | $129,620 | -5% | 0.88 |
| Salt Lake City, UT | 19,040 | $129,600 | -5% | 2.12 |
| Houston, TX | 22,940 | $129,440 | -5% | 0.64 |
| Kansas City, MO | 12,160 | $124,990 | -8% | 1.02 |
| Pittsburgh, PA | 10,320 | $124,500 | -8% | 0.85 |
Location quotient compares how concentrated this occupation is in the metro against the national average. A value above 1 means the metro has more of this work than its size would predict.
The location quotient column is the more useful one for hiring. A high median tells you what a role costs; a high quotient tells you whether the people exist. San Jose, San Francisco, Seattle, Washington, D.C., Denver, Austin each have a quotient of 1.5 or above, meaning the work is concentrated there well beyond what the size of the local economy would predict. Those are the markets where a search is likely to be quick and competitive at the same time, and where a counter-offer is most likely to take a candidate off the table late in the process.
The opposite case is worth planning for too. In a metro with a low quotient, the total pool is small even when wages look reasonable, so the realistic options are to widen the search radius, accept a longer time to hire, or bring the capability in from outside the local market entirely. That last option is what most teams are weighing when they come to us.
Hiring risks worth naming
Every one of these has produced a bad hire somewhere. They are written down so that the process tests for them deliberately rather than discovering them in month three.
Client experience presented as server experience. Writing queries is not building a server. The hard parts are entirely on the server side.
No production load experience. Ask about the N plus one problem. Anyone who has run GraphQL at scale will answer immediately.
Weak authorisation thinking. The area where GraphQL creates real risk relative to REST, and where the failures have been public.
Adopting it without needing it. Ask when REST would be better. Someone with no answer may build complexity you gain nothing from.
Hiring GraphQL developers by metro area
Wages for this occupation vary more between US metro areas than most budget models assume. Each page below sets out the published employment and wage figures for that market, how it compares with the national picture, and what the local industry mix means for the kind of GraphQL developer who will be available.
- New York, NY $166,830 median
- Seattle, WA $167,280 median
- San Jose, CA $213,110 median
- Washington, D.C. $154,930 median
- San Francisco, CA $186,640 median
- Dallas-Fort Worth, TX $133,290 median
- Los Angeles, CA $160,920 median
- Boston, MA $166,090 median
- Chicago, IL $134,380 median
- Atlanta, GA $132,960 median
- Austin, TX $134,120 median
- Phoenix, AZ $131,750 median
- Philadelphia, PA $133,040 median
- Minneapolis-St. Paul, MN $130,920 median
- Denver, CO $137,610 median
- Detroit, MI $130,760 median
- Houston, TX $129,440 median
- Charlotte, NC $135,920 median
- San Diego, CA $163,270 median
- Salt Lake City, UT $129,600 median
- Miami, FL $132,650 median
- Portland, OR $156,000 median
- Baltimore, MD $138,900 median
- Tampa, FL $130,450 median
- Orlando, FL $129,620 median
- Raleigh, NC $132,770 median
- Kansas City, MO $124,990 median
- Pittsburgh, PA $124,500 median
Frequently asked questions
Should we use GraphQL or REST?
GraphQL when several clients with different data needs consume the same data, when round trips are expensive as on mobile, or when your front end evolves faster than your back end can add endpoints. REST when you have one client with stable needs, because it is simpler, caches naturally over HTTP, and has fewer ways to go wrong. Adopting GraphQL for a single web front end is a common way to buy complexity without the benefit.
Does GraphQL make our API faster?
It reduces round trips, which genuinely helps on high-latency connections. It does not make the server faster, and a naively implemented GraphQL server is usually slower than the REST endpoints it replaced because of the N plus one problem. The performance benefit is real on the client side and has to be earned on the server side.
Is GraphQL less secure than REST?
It is not inherently less secure and it is easier to get wrong. A single entry point exposing a traversable graph means authorisation must be applied consistently at field level, and a field reachable by an unexpected path can leak data. Combined with the need for query complexity limits, it asks more of the implementation than REST does.
Why is our GraphQL API slow?
Almost certainly the N plus one problem: resolvers issuing a database query per item rather than batching. Field-level tracing shows it immediately. The fix is a data loader, and the fact that it was not there from the beginning is the more interesting finding.
How do we cache GraphQL?
Not the way you cache REST, which surprises teams. Queries typically go over POST to one endpoint, so HTTP caching does not apply. The answers are normalised client-side caching, persisted queries that make requests cacheable, and server-side caching at the data layer rather than the response layer.
Should we adopt federation?
Only with several teams owning parts of one graph and a genuine need for a unified API across them. It is a substantial organisational and technical commitment, with its own tooling, governance and failure modes. For a single team it adds complexity with no benefit, and it is frequently adopted aspirationally.
Can clients write queries that break our server?
Yes, and that is the main thing to design against on a public endpoint. A deeply nested or broad query can be extremely expensive. Depth limits, complexity scoring and, where the clients are yours, persisted queries that allow only known operations are the standard protections and should be in place before launch rather than after an incident.
Do we need GraphQL-specific developers?
Less than you might expect. A strong back-end developer learns the server side quickly, and the genuinely hard parts, namely data access performance, authorisation and abuse protection, are ordinary back-end skills applied to a different shape. Test those rather than testing GraphQL familiarity.