Skip to main content

· 7 min read
Benjie
Jem

In the first Grafast Working Group, we outlined 4 major issues in Grafast that needed to be addressed before we could think about general release. The fourth, and final, epic has now been solved!

  • ✅ Global dependencies — solved via “unary” steps
  • ✅ Early exit — solved via “flags”
  • ✅ Eradicating eval
  • Polymorphism — this release!

In previous versions of Grafast there was the possibility of exponential plan branching due to the naive method of resolution of abstract types — a known issue raised in the first Grafast working group as one of four “epics” to be solved before v1.0. This release of [email protected] fixes this final epic through a complete overhaul of the polymorphism system. Let’s take a look!

Polymorphism epic achieved

By moving the responsibility of polymorphic resolution from field plan resolvers into the abstract types themselves, we’ve centralized this logic, simplified field plan resolvers, and unlocked more optimization opportunities and greater execution efficiency. We no longer have the concept of “polymorphic capable” steps: any step may now be used for polymorphism. Abstract types now gain a planType method responsible for taking a “specifier” from the field plan resolver and returning a step representing the name of its concrete object type along with subplans for each possible object type.

To solve the problem of exponential branching, we merge the new specifier steps from all previous polymorphic branches into a single “combined” step before planning the next level of polymorphism.

A plan diagram showing the old way polymorphism was handled. The nodes can branch exponentially. A plan diagram showing the new way, the branches are combined back together before moving to the next layer of resolution.

On the right is the new handling of polymorphic resolution. getPetIds and getServiceAnimals both fetch an Animal ID and so they are combined together in order to fetch all of the required Animals by their IDs. Once the IDs are fetched, the nodes can branch out to the different Animal types.

· 8 min read
Benjie

In the first Grafast Working Group, we outlined 4 major issues in Grafast that needed to be addressed before we could think about general release. With this release, 3 of these are now complete!

  • ✅⤵️ Global dependencies — solved via “unary” steps
  • ✅⤵️ Early exit — solved via “flags”
  • ✅🎉 Eradicating eval — this release!
  • 🤔🔜 Polymorphism

We’re proud to announce that the third of these, eradicating eval, is now addressed with the launch of [email protected], and the approach has been fully adopted and tested via incorporation into [email protected].

Input evaluation moved to runtime

Since the beginning, Grafast has had the ability to add plan resolvers not just to fields, not just to arguments, but also to input object fields (including those within lists). This made Grafast’s planning really ergonomic for things like nested filters. But it turns out it’s really problematic for certain shapes of input — planning would put constraints on the variables compatible with the plan, requiring potentially unlimited numbers of operation plans needing to be built for the same GraphQL document. Worse: for large input trees involving lists, the number of steps generated could be overwhelming, resulting in the deduplication phase taking excessive time.

One particular user example that could cause 4 minutes of planning time from just a 100kB input made it clear that we had overreached with using plan resolvers too deep into inputs; so we’ve scaled it back so that you can only add plan resolvers to fields and arguments, you can no longer attach applyPlan or inputPlan to input object fields. This was something that we used a lot in PostGraphile and its various plugins, but very few people (no-one?) used externally so it was ripe for removal.

That problematic query that took 4 minutes to plan before? It now takes 1.1ms to plan, yielding a 200,000x speedup!

· 6 min read
Benjie

Grafast is finally here a new holistic execution engine for GraphQL. It enables greater efficiency across the entire backend stack by leveraging the declarative nature of GraphQL to give your business logic a better understanding of everything it needs to do. It’s backwards compatible, so you can adopt it incrementally within your existing schema and it’s finally ready to try with the grafast module on npm; or check out the source code on GitHub!

I launched Grafast v0.1 at GraphQL Conf, above is the full video of my talk which covers what Grafast is and how it can improve application performance, reduce operational costs, all without being a significant burden on developers.

Grafast Working Group

There’s still decisions to be made and edges to be smoothed before Grafast can become a specification that can be implemented in any language. If the potential of this technology is interesting to you, please join the Grafast working group and get involved. We all deserve our future of easy GraphQL execution efficiency!