Open-source project
urql-graphql/urql avatar
urql-graphql/urql

urql: a GraphQL client you assemble from exchanges

The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.

8,977 stars480 forksTypeScriptMIT

At a glance

What is it?
urql is a TypeScript GraphQL client for React, Preact, Vue, Solid and Svelte that ships small defaults and lets you add normalized caching later. This article covers the exchange pipeline, a first setup, and where the design costs you.
Who is it for?
Adopt urql if you want a small default GraphQL client and intend to shape its request pipeline yourself through exchanges, or if you need one client across React, Preact, Vue, Solid and Svelte. Do not adopt it expecting normalization out of the box: the README treats @urql/exchange-graphcache as an add-on, and the default is document caching.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What urql solves, and who ends up using it

Most GraphQL clients make a choice for you on day one: either you get a minimal cache and rewrite later, or you inherit a normalized store and its configuration before you have a single screen working. urql takes the first path deliberately. The README describes it as "a GraphQL client that exposes a set of helpers for several frameworks" and says it is "built to be highly customisable and versatile so you can take it from getting started with your first GraphQL project all the way to building complex apps".

The intended audience is visible in the repository topics: complex-apps, exchange, graphql-client. That is a client for teams who expect their data layer to change shape as the product grows, and who would rather compose that change than configure it up front. The default behaviour is described as "Logical but simple default behaviour and document caching", which is a smaller promise than a normalized cache makes. If your application is a handful of screens reading from one API, that smaller promise is usually enough.

The second audience is framework breadth. The README lists React, Preact, Vue, Solid and Svelte under a single package, and the examples directory mirrors that with folders for react, vue3, svelte, solid, solid-start and react-native. A team maintaining more than one frontend framework in the same organisation gets one mental model instead of one per framework.

Exchanges: the request pipeline you actually program

The mechanism urql is built around is the exchange. The README points to a documentation page titled "Authoring exchanges" and lists customisable behaviour "via exchanges" as the first feature. The architecture documentation is a separate top-level section, which tells you the project expects you to read it rather than treat the client as a black box.

The practical consequence is that every operation, whether a query, mutation or subscription, passes through an ordered chain of exchanges before it reaches the network and back again. Caching, retries, authentication refresh and pagination are all expressed as links in that chain rather than as options on a constructor. The examples directory confirms this shape: with-retry, with-refresh-auth, with-apq, with-pagination, with-infinite-pagination, with-graphcache-pagination, with-graphcache-updates, with-multipart, with-defer-stream-directives, with-subscriptions-via-fetch. Each of those is a behaviour implemented as a composable piece rather than a flag.

That is the real trade-off. A pipeline you assemble is debuggable, because you can reason about order and insert logging or a short circuit at a known point. It is also a pipeline you can assemble incorrectly. Exchanges that both handle the same operation, or that sit on the wrong side of the cache, produce behaviour that is hard to explain from the outside. The README's claim of "Easy debugging with the urql devtools browser extensions" is the counterweight: the project expects you to inspect the pipeline rather than guess at it.

Installing urql and rendering a first query

urql is published on npm, and the README points at the @urql/core package page as the canonical package. The repository is a pnpm workspace, with packages/ and exchanges/ as the two source directories, but that layout matters only if you intend to contribute. For consumption you install from the registry.

Start with the core package and a framework binding. The README says one package gets you a working client in React, Preact, Vue, Solid and Svelte, so the binding is the second install.

bash
npm install urql graphql

The README's feature list puts the client and its helpers in one package, so a single install covers the framework binding and the core. After installation you create a client with a URL and wrap your application in the provider that the framework binding exports. The documentation's Basics section holds the Getting Started guide, and the README says that guide is what you need "when first using urql".

For the first real use, the repository gives you a working reference rather than a snippet to retype. The examples folder contains a complete app per framework, and examples/with-react is the smallest entry point.

bash
cd examples/with-react
pnpm install
pnpm dev

The examples are part of the pnpm workspace declared by examples/pnpm-workspace.yaml, which is why the install command is pnpm rather than npm inside that directory. What you should see is a running app issuing queries through urql. Read that example before writing your own client, because it shows the provider setup and the query hook together, which is the part most people get wrong on the first attempt.

To move past document caching, the README names the package explicitly: "Normalized caching via @urql/exchange-graphcache". That is a separate install and a separate exchange in the pipeline, not a setting on the client.

Where urql is the wrong choice

The default caching model is the first limitation, and it is a design decision rather than a gap. Document caching stores results by operation. If two queries return the same entity through different documents, the default client does not know they are the same object. The README is explicit that normalized caching arrives through @urql/exchange-graphcache, which means the behaviour that many teams assume is baseline is an add-on you install, configure and maintain. A team that wants normalization without thinking about it is choosing the wrong client.

The second limitation is the exchange model itself. It is a strength for teams who will read the Architecture and Advanced documentation sections. It is a liability for a team that wants a client with a small, fixed set of options and no interest in ordering a pipeline. Every custom behaviour becomes code you own. The examples directory is generous, but an example you copy is still code you maintain.

Third, version transitions are real work. The README states that upgrading to v4 has a migration guide "posted as an issue" at urql-graphql/urql issue 3114, and the release history shows the project is now on [email protected]. A migration guide delivered as an issue thread rather than a documentation page is a signal about how much of the upgrade path is prose and how much is reading the changelogs. Each package carries its own CHANGELOG.md, for instance packages/core/CHANGELOG.md, so an upgrade means reading per-package notes rather than one document.

Finally, the README does not document a rollback path for a failed release or a downgrade procedure. If you need that, it is not documented.

urql compared with a query-cache-first client

The most common comparison point for urql is React Query, and the difference is architectural rather than cosmetic. React Query is built around a query cache with keys and invalidation, and it is not a GraphQL client: you write the fetch function and it manages caching, retries and staleness around whatever that function returns. urql is a GraphQL client with an operation pipeline, and caching is one exchange among several.

That distinction changes what you configure. With a query-cache-first library, you spend your time on cache keys, stale times and invalidation calls. With urql, you spend it on exchange order and, if you adopt graphcache, on how normalized entities are keyed and updated. The examples directory reflects the second model: with-graphcache-updates and with-graphcache-pagination exist because normalized cache updates are a real configuration surface, not a default.

There is also a framework-coverage difference. The README positions urql as one package across React, Preact, Vue, Solid and Svelte, with examples for each. If your organisation runs more than one of those, a single client and a single exchange vocabulary is a concrete advantage that a React-only library does not offer.

Maintenance cadence, releases and the MIT licence

The repository is not archived, and the last push was on 2026-09-09. Recent releases are frequent: [email protected] on 2026-08-21, @urql/[email protected] on 2026-06-22, and [email protected] on 2026-06-15. The README states that the project "was founded by Formidable and is actively developed by the urql GraphQL team".

The release process is documented and worth knowing before you depend on it. New releases are prepared with changesets, changelog entries are added to each pull request, and "Version Packages" pull requests are merged to publish. The README also notes that @canary releases are available on npm "if you'd like to get a preview of the merged changes". For a team that needs to track upstream fixes, that means watching pull requests and per-package changelogs rather than a single release feed. The repository also publishes to JSR, as the package.json scripts jsr and jsr:dryrun show, filtered to @urql/core.

urql is MIT licensed. In practical terms that permits commercial use and modification with the licence and copyright notice retained, but the repository's LICENSE file is the authority and this is not legal advice. The dependency surface is worth a look for your own audit: package.json lists a large set of devDependencies including Babel, Rollup and ESLint plugins, plus @0no-co/graphql.web, though those are build-time concerns for the repository rather than runtime dependencies of the published packages.

Editorial conclusion

Adopt urql if you want a small default GraphQL client and intend to shape its request pipeline yourself through exchanges, or if you need one client across React, Preact, Vue, Solid and Svelte. Do not adopt it expecting normalization out of the box: the README treats @urql/exchange-graphcache as an add-on, and the default is document caching. Before committing, install it, render one query, and then read the Architecture and Advanced documentation sections to confirm the exchange model matches how your team debugs data flow.

Frequently asked questions

What is urql and what is it used for?

urql is a GraphQL client that exposes helpers for React, Preact, Vue, Solid and Svelte. It is designed to be customisable through exchanges, so you can start with simple document caching and add normalized caching later via @urql/exchange-graphcache.

How do I install urql?

It is published on npm; the README points at the @urql/core package page. The repository's examples, such as examples/with-react, are part of a pnpm workspace, so they install with pnpm install inside the example directory.

Does urql support normalized caching?

Yes, but not by default. The README lists normalized caching as a feature provided through @urql/exchange-graphcache, a separate package and exchange, while the built-in behaviour is described as document caching.

Which frameworks does urql support?

The README lists React, Preact, Vue, Solid and Svelte under one package, and the examples directory contains a separate example for each, plus with-next, with-react-native and with-solid-start.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. urql-graphql/urql on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/urql-graphql-urql.svg)](https://hysenlabs.com/projects/urql-graphql-urql)