Closing gaps 2026/06/14 ​
the tl;dr ​
Today, we're releasing [email protected] with:
- Speed ups across the board and support for larger projects
- Massively faster and more robust
gql.tada turboruns - Improved
referencesandextendssupport for monorepos - Quality of life updates in GraphQLSP for all supported features
- A new
gql.tada scanCLI command for agentic analysis - A typed
readResultAPI for typed testing
The previous devlog now lies almost two years back, and we since considered gql.tada a "finished" and feature-complete library. However, this meant we didn't address a few shortcomings and RFCs for quite a while, given that we didn't work on any projects using gql.tada ourselves in that time (which is now changing).
We still believe that gql.tada, as it stands, offers the best trade-offs for bringing typed GraphQL to TypeScript front-end projects. It forms a low-friction, low-decision framework, built on a triple architecture:
- the inference types in the client-side library,
- the supporting features in its TypeScript plugin (via our GraphQLSP project),
- and the CLI, offering extended features that connect the in-code GraphQL documents to your GraphQL schemas, and to the TypeScript language server.
Hence, it's worth revisiting the open problems and RFCs that went unaddressed.
Turbo revisited for larger codebases ​
Codebases with GraphQL follow a predictable growth trajectory, and schemas with thousands of fields, alongside front-ends with hundreds of GraphQL documents, aren't unusual. TypeScript itself helped us out here, improving its inference performance and laziness on evaluating types.
gql.tada's Turbo typegen is more relevant than ever in this context. As we edit GraphQL documents, instant feedback and type changes are essential for a good developer experience. Afterwards, generating types to speed up inference and reducing the load on the TypeScript type checker maintains that experience in CI and for a larger team.
However, longstanding issues we had to address were Out of Memory errors in the Turbo command, and some other usability problems of the command.
As of the latest version,
- Out of Memory errors should be solved
- If an error occurs, it's now reported, as intended
- Cancelling the
turbocommand works, as expected - Issues with
moduleResolutionwere fixed
Turbo speeds up too ​
To that end, supporting larger repositories also meant we needed Turbo to run a lot faster than it did before.
To make the command's runtime more predictable, we now attach a fingerprint hash to each cached type entry. This allows us to skip recomputing a type entirely when it likely hasn't changed. We also now scope TypeScript source files more aggressively which avoids the command having to check source files that cannot contain GraphQL documents.
The GraphQL document scanner also now skips modules that clearly don't contain GraphQL documents, or call expressions that don't look like GraphQL. (#537, #539, graphqlsp#392)
Lastly, a few strategic changes in the type-level parser (#532, #542) mean that the type inference itself is now slightly faster and cheaper.
All in all, on one of our test projects, this reduces Turbo's time from multi-minute (2+ minutes) down to 30s cold, and 6s warm. Fast enough to run frequently, without worries, we believe.
Larger repos and monorepos ​
As gql.tada was increasingly used in larger projects, a common pattern of issues emerged and the feature request for project references became more relevant.
As of this latest version, we fixed several issues around our extends support (such as with #545), and added support for project references, which is a common pattern now implemented by a few frameworks' presets and templates.
Overall, we don't want the experience to degrade while your project grows, and these subtle fixes and improvements should go a long way in ensuring that this remains the case.
Plugin quality of life changes ​
The TypeScript plugin that extends the in-editor experience, GraphQLSP has received a few major upgrades that should improve the day-to-day experience of using gql.tada.
The unused field detection warning has been entirely re-written, making use of raw TypeScript checker symbols throughout now. This was a change we planned but had to shelve a while back, but are introducing now. This should make unused field detection warnings more accurate and less of a nagging warning.
We toned down the co-located fragment warning too, hopefully allowing more of you to not have to disable it. We know that many projects aren't willing or ready to take full advantage of masked and co-located fragments yet. This change reflects this, muting the related warning in more cases.
Lastly, we noticed that a lot of users struggle to get over the "first hump" of setting up gql.tada's configuration and activating the TypeScript plugin properly. While the CLI can be used as an alternative activation point, this obviously isn't a great hurdle to be stuck at. Errors are now surfaced as diagnostics, so, once the TypeScript plugin is active, it self-reports any issues in your configuration.
These are all important quality of life changes that should go a long way in keeping to gql.tada's idea of having a smooth and coherent experience, rather than being stuck setting tooling up forever.
Typed testing with readResult ​
For the longest time, we knew that a rough edge of gql.tada is typing synthetic data, for example for testing. While unsafe_readResult works as-is today, by unsafely casting, this doesn't actually type check your result objects. That, however, is an important guard rail to be able to maintain tests (or to write normalised caching logic).
As of this release, we're adding a type-safe version, readResult.
import { readResult } from 'gql.tada/testing';
const data = readResult(
query,
{ pokemon: { id: '001', name: 'Bulbasaur' } },
[pokemonItemFragment, pokemonNameFragment]
);All test APIs, maskFragments, unsafe_readResult, and readResult are now exposed on a gql.tada/testing entrypoint, to logically group them.
Not having readResult implemented was a painful omission for us before, however, maintaining complex TypeScript types, measuring their performance, and experimenting with different shapes for them was a significant burden to us when developing gql.tada. To be fully transparent, agentic development has changed this and allowed us to rapidly test ideas until we landed on ones that worked in a matter of hours, rather than days.
API Reference
Learn more about the readResult function
Agentic Analysis ​
Staying on the topic of agentic development, we're introducing an experimentalgql.tada scan command. This can either output a report of several properties of your codebase as an in-terminal or JSON report, or be used with --graph to output a graph structure in JSON format, of all GraphQL documents in your codebase.
As a tool, gql.tada is in a unique position. It has access to your GraphQL schemas, your GraphQL documents, and the TypeScript type checker. Connecting all three, it can out-of-the-box provide a lot of insights and data, that's otherwise hard to derive with one-off scripts.
We hope that this command will be useful when refactoring or maintaining large codebases with gql.tada.
CLI Reference
Learn more about the scan command
Where does that leave us? ​
We've closed 20 long-standing issues in the gql.tada repository for this batch of releases, and can finally say that we're not only reasonably feature complete but also ready for bigger projects than before.
As I've written in the opening, I still believe that gql.tada has made a set of careful trade-offs and design decisions that leave it at a developer experience sweet spot, while also promoting the more sustainable patterns of GraphQL codebases.
We now have a comprehensive answer for:
- TypeScript inference performance (plus the Turbo command)
- Monorepos and larger projects (with multi schema,
references, andextendssupport) - Safe and scalable GraphQL with private APIs (with persisted documents support)
- Agentic development (with existing guard rails and now the
scancommand) - Testing and manual typing (with
gql.tada/testingandreadResultsupport)
Reasonably speaking, migration to gql.tada is also easier than ever given that agents can now autonomously read the docs and migrate a project over for you (which we've seen firsthand on a project that's migrating over).
We also feel that gql.tada is a low-effort entrypoint to starting a nicely structured GraphQL project, promoting fragment co-location over fragment reuse. Or, as Janette Cheng succinctly put it: "Fragments - They're not for re-use!"
This all comes at a time when GraphQL isn't a "hot topic" anymore, and it's hard to tell whether its adoption is diminishing or growing. There's a lot of confusion and discourse in the broader developer community about the benefits and trade-offs of GraphQL, as its malleability lets developers leave the "sweet spot" of GraphQL much too easily. Or, as we may add to this discourse: "GraphQL - It's not about solving over-fetching!"
We hope that gql.tada provides a good counterpoint and features that continue to make sense when you do choose to use GraphQL. If you enjoy it, consider writing and posting about how gql.tada helps your project!