Blog

  • Behind the Scenes of WPGraphQL’s New Automated Release Process

    Publishing a new release for WPGraphQL has historically required several manual steps—updating changelogs, determining semantic version bumps, preparing upgrade notices, and ensuring that every piece of documentation reflects the correct information. While I had a process in place, it wasn’t as efficient as it could be, and the potential for human error was always there.

    Over the past few weeks, I set out to automate as much of this as possible. This blog post walks through why I tackled this, how I iterated on different approaches before landing on the final implementation, and where I see this evolving in the future.

    Why Automate the Release Process?

    When it comes to maintaining an open-source project like WPGraphQL, consistency and accuracy in releases are crucial. I had been following a structured but manual process that involved:

    • Writing and maintaining changelogs
    • Updating the readme.txt for WordPress.org
    • Ensuring proper semantic versioning (major, minor, patch)
    • Writing upgrade notices for breaking changes
    • Publishing the release

    While this process worked, it was:

    • Time-consuming: Even with a checklist, it required multiple steps every time a release was prepared.
    • Prone to human error: Forgetting a step or misclassifying a change could lead to inconsistencies.
    • Hard to scale: As WPGraphQL continues to grow, I needed a more robust and repeatable approach.

    By automating these steps, I aimed to:

    • ✅ Save time by reducing the manual overhead of preparing releases
    • ✅ Reduce errors by ensuring that every PR gets documented correctly
    • ✅ Improve visibility into what’s changing in WPGraphQL releases
    • ✅ Ensure consistency across releases and documentation

    How I Got Here: Iterating on the Solution

    My goal was to create a workflow that would automatically track changes from pull requests and use those to generate release notes, changelog entries, and semantic version bumps.

    Exploring Solutions

    I initially considered using @changesets/cli, a tool commonly used in JavaScript monorepos for managing changelogs and versioning. However, since WPGraphQL is a WordPress plugin (not a monorepo) and follows a different release structure, I opted to implement a custom approach while borrowing the core concept: collecting markdown files per PR to document changes.

    Prototyping with Test Repositories

    At first, I worked on some GitHub Workflows locally, and tested using the GitHub Local Actions VS Code extension, and when I thought I had things working well, I merged some workflows into the WPGraphQL repo, thinking they were in a solid state.

    But then… they didn’t run the same in GitHub as they were locally. 😤

    I found myself pulling out my hair (or lack thereof) debugging. Instead of continuing to troubleshoot in the main repo, I took a step back and started experimenting in separate repositories to isolate issues and test more freely.

    I created multiple test repositories to refine the approach:

    1. Automation Tests – My first attempt at testing workflow concepts.

    2. Workflow Tests – A fresh start after hitting roadblocks with the initial approach.

    3. WPGraphQL Workflow Tests – A fork of WPGraphQL to see how these workflows behaved in a real-world repo structure.

    Through trial and error, I was able to pinpoint issues, tweak the workflows, and ultimately get them running smoothly. You can see the results of these manual tests in the workflow test releases.

    Once I was confident in the implementation, I merged them back into WPGraphQL, where they successfully generated v2.1.1.

    How the Workflows Work

    The final implementation consists of two GitHub Actions workflows:

    Changeset Generation Workflow

    View on GitHub

    • Runs when a PR is merged into develop
    • Creates a .changeset/ markdown file documenting the change
    • Helps maintain a structured history of changes

    Release Workflow

    View on GitHub

    • Runs when preparing a new release
    • Aggregates changesets into a full changelog
    • Determines the correct version bump (major, minor, patch)
    • Updates readme.txt with upgrade notices
    • Publishes the release

    Future Automation Plans

    Now that the core release process is automated, I’m thinking about how to improve workflows for larger milestone features.

    Handling Milestone-Based Feature Work

    Some features, like custom scalar support, will require significant iteration before they’re ready to merge and release. My idea is to create a milestone tracking system where:

    • 🚀 Feature branches (feat/email-scalar, feat/datetime-scalar, etc.) merge into milestone branches (milestone/custom-scalars).
    • 📌 Each feature PR generates a changeset, which gets collected in the milestone PR.
    • 🔄 Changes accumulate within a milestone branch, giving visibility into larger features while allowing normal feature releases to continue.
    • 📅 When a milestone is complete, all associated changesets merge into develop, triggering a proper release workflow.

    This approach allows larger features to be worked on in parallel while maintaining a clear record of what’s being developed.

    I’ll likely experiment with these workflows in the WPGraphQL Workflow Tests repository.

    Final Thoughts

    Open-source projects like WPGraphQL benefit tremendously from automation. The more we can reduce friction in the development and release process, the better we can focus on delivering new features, improving performance, and maintaining stability.

    These workflows have already made releasing WPGraphQL easier, and I’m excited to continue refining them and exploring how we can automate more aspects of feature development and release tracking.

    I also want to explore making some of these processes a bit more re-usable so we can easily implement them on some of the other repos, such as: WPGraphQL Smart Cache, WPGraphQL IDE, WPGraphQL for ACF and others.

    Who knows, perhaps I may even explore a monorepo setup to see if that could help increase efficiencies for both maintainers and contributors?

    If you have thoughts on this approach or ideas for improvements, feel free to reach out on Discord or GitHub! 🚀

  • WPGraphQL v2.0 is Here: What You Need to Know

    🚀 WPGraphQL v2.0.0 has officially been released! This is a major update that includes breaking changes, so if you’re using WPGraphQL in production, please review the details below to ensure a smooth upgrade.

    👉 View the Release on GitHub

    👉 Technical Update: Breaking Changes

    Why WPGraphQL v2.0?

    The primary motivation behind this release was upgrading WPGraphQL’s underlying GraphQL-PHP library. This upgrade unblocks us from shipping long-awaited features, such as the @oneOf directive, which will enable polymorphic input types. I’ve been talking about this since 2017 (GitHub comment here), and we’re finally in a position to make it happen!

    Additionally, this release encourages users to keep their server stack updated (PHP, WordPress, and related dependencies), leading to better performance, security, and long-term supportability.

    What’s Changed in WPGraphQL v2.0?

    🚨 Breaking Changes

    • Dropped support for PHP below 7.4
    • Dropped support for WordPress below 6.0
    • Error handling changes due to updates in graphql-php (see full details in the technical update post)

    🔥 New Features Over the Last Few Months

    While v2.0 itself doesn’t introduce major new features, recent releases included several improvements, all of which are now part of v2.0:

    • 🛠 New Extensions Page
    • 🖥 New CLI arguments in wp graphql generate
    • 📂 New fields on MediaItem for file and filePath
    • 🚨 New SemVer update checker (warns about breaking changes before updating)
    • New fields on EnqueuedAsset and EnqueuedScript

    🔗 See full release notes

    How to Upgrade to WPGraphQL v2.0

    For many users, no immediate action is required. However, if you’re running an outdated version of PHP or WordPress, you’ll need to upgrade your stack before updating WPGraphQL.

    • Step 1: Check your PHP version (must be 7.4+) and WordPress version (must be 6.0+)
    • Step 2: Test your site and any WPGraphQL custom extensions in a staging environment
    • Step 3: Follow the upgrade guide:

    👉 Technical Update: Breaking Changes

    👉 General WPGraphQL Upgrading Guide

    Where to Get Help?

    If you run into issues or have questions, we encourage you to reach out:

    💬 GitHub Issues – Report bugs or discuss issues

    💬 Join the WPGraphQL Discord – Connect with the community

    Special Thanks to Our Contributors

    This release would not have been possible without the incredible contributions of our community, especially Dovid Levine (@justlevine), who put in countless late nights and weekends helping maintain WPGraphQL and grow the headless WordPress ecosystem. 🎉

    What’s Next for WPGraphQL?

    With v2.0 released, we’re excited to move forward on several highly requested features, including:

    • 🛠 Custom Scalars
    • 🏗 @oneOf Directive (enabling polymorphic input types)
    • 📷 MediaItem Enhancements

    Upcoming Event: Ask Questions Live!

    I’ll be at the Headless WordPress Community Event on Monday, Feb 24, where you can ask questions about WPGraphQL v2.0 and beyond. This is hosted by the Headless WP Discord communityjoin here!


    🚀 We’re excited for the future of WPGraphQL, and we appreciate all of you who have helped make this possible.

    Happy querying!

  • WPGraphQL v2.0 Is Coming – Here’s What You Need to Know


    We’re excited to announce that WPGraphQL v2.0 is coming soon! This release brings key improvements such as better performance, stricter validation, and more flexibility for developers.

    This change introduces breaking changes that may affect your site or project.

    For technical details on breaking changes and developer recommendations, read the WPGraphQL v2.0 Technical Update Guide.

    Release Timeline


    We plan to release WPGraphQL v2.0 in the first week of February. This timing allows developers to prepare after the holiday and start-of-year rush.

    We’ve already opened a Beta Pull Request for testing. If you’d like to get an early look, test your projects against the beta and let us know your feedback!

    Breaking Changes


    WPGraphQL v2.0 will require PHP 7.4 or newer. Please ensure your server is running PHP 7.4 or newer before installing the new version.

    We’re upgrading WPGraphQL’s underlying GraphQL engine, graphql-php, from v14.11.10 to v15.8.1. This brings modern improvements but also introduces changes developers need to be aware of.

    We’ve written up a more technical guide that gets into more detail about the changes.

    What you should do

    • Check your PHP version: Ensure your site runs PHP 7.4+
    • Test in a staging environment: Test the update in a staging environment before applying it to your live site.
    • Check for compatibility: Ensure custom plugins or WPGraphQL extensions are compatible with v2.0.

    Looking Ahead

    While we work toward the final v2.0 release, we’ll continue adding new features and improvements. Some features currently in development include:

    • Extensions Page: An enhanced admin experience for managing WPGraphQL extensions.
    • Semantic Version Check: A system to reduce the risk of auto-updates causing breaking changes.

    Learn More & Stay Informed

    For developer-focused technical details, visit our WPGraphQL v2.0 Technical Update Guide. We’ll share more updates as the release approaches.

  • WPGraphQL v2.0 Technical Update & Breaking Changes

    WPGraphQL v2.0 is coming soon, featuring an upgrade to its underlying GraphQL engine, graphql-php, from v14.11.10 to v15.8.1.

    This upgrade brings better performance, stricter validation, and enhanced extensibility. However, it also introduces breaking changes that may impact developers extending WPGraphQL or maintaining custom plugins.

    This guide highlights technical changes, developer recommendations, and actions needed to prepare your projects.

    PHP Version Requirement:

    WPGraphQL v2.0 will require PHP 7.4 or newer, raising the minimum requirement from PHP 7.1.
    This change follows the adoption of graphql-php v15+, which also requires PHP 7.4+. Ensure your hosting environment is updated before testing the beta or upgrading to v2.0.

    By adopting the latest graphql-php, WPGraphQL inherits several breaking changes that may impact developers extending WPGraphQL. Below, we’ve highlighted the most important changes, though we also recommend reviewing the graphql-php release notes for more detail.

    Key Breaking Changes:

    Error Response Changes:

    • “category” field removal on errors: The “category” field has been removed from GraphQL error responses. If your application depends on this field, adjust your error-handling logic accordingly.
    • debug entries moved: graphql-php now places debug information under the extensions key of the error response. Ensure your application properly handles this structure.
    • serialization errors: Errors during leaf value serialization will now throw SerializationError, replacing previously thrown generic errors.
    • HTTP Status Code Change: For graphql requests made over HTTP using the POST method, if the request does not contain the Content-Type header specifying application/json, the response will have HTTP Status of 415 instead of 500. (see: https://github.com/wp-graphql/wp-graphql/pull/3291)

    Schema and Type Management Updates:

    • Topological Schema Ordering: graphql-php now orders schema definitions based on type dependencies and user-defined types. Be aware that this could change the output of introspection queries, especially when dynamically generating types.
    • Standard Type Enforcement: Overriding built-in GraphQL Types in the schema is no longer supported. Consider using custom types instead of overriding built-in types directly.

    Input and Enum Parsing Enhancements:

    • Lazy Loading for Input Objects and Enums: graphql-php now supports lazy-loading for input objects and enums. This can improve performance for schemas with complex, deeply nested types. Developers defining custom types should adjust type definitions if needed.

    Server and HTTP Behavior Adjustments:

    • Request Validation: Requests with invalid JSON will now trigger a RequestError instead of a generic error. This makes debugging request payload issues easier by returning clear error messages early in the request lifecycle.

    Recommended Actions:

    • Upgrade PHP: Ensure your environment runs PHP 7.4+ before updating WPGraphQL.
    • Review Error Handling: Update how your application handles GraphQL errors, including changes to the category field, the new location of debug entries and the HTTP Status Code change for invalid Content Type headers.
    • Test Plugin Compatibility: Test any custom plugins, WPGraphQL extensions, and GraphQL queries in a staging environment. Ensure compatibility before deploying to production.

    Resources and Links:

  • WordPress Meets WASM: Full Power of the CMS in Any App

    Last week at WASMCon 2024, I had the privilege of speaking about something I’m incredibly passionate about: using WordPress in non-traditional ways. My talk, “WordPress Meets WASM: Full Power of the CMS in Any App,” explored how WordPress, a platform many associate with traditional websites, can now be embedded and run virtually anywhere, thanks to technologies like WebAssembly (WASM).

    Below is a recap for those who prefer reading over watching videos.

    A Journey of Non-Traditional WordPress Use

    I began by sharing a personal story from 2006, when I stumbled upon a Flash-based website for the marketing agency Leo Burnett that inspired me to learn Flash development.

    (NOTE: You can view the 2006 version of the Leo Burnett website on Archive.org)

    That curiosity eventually led me to WordPress when I needed a way to manage content in a Flash site without requiring the end user to know Flash. Back then, I discovered WordPress and its XML-RPC API that could be used to connect a Flash front end to a WordPress back end. While that project didn’t go far, it was my first step into the world of WordPress, and it changed the trajectory of my career.

    Fast forward to 2016, I created WPGraphQL, a free, open-source plugin that allows developers to use WordPress as a GraphQL API. This opens up countless possibilities for building decoupled or headless front ends with frameworks like Next.js, Gatsby, and Astro, or even native mobile apps. The content lives in WordPress, but how it’s rendered is entirely up to the developer.

    Enter WordPress Playground

    While WPGraphQL has made headless WordPress more accessible, developers still face challenges in quickly setting up environments to test plugins or content workflows. Traditionally, this would require setting up a local server with PHP, MySQL, and Apache.

    WordPress Playground changes everything.

    WordPress Playground leverages WebAssembly to run WordPress entirely in the browser — no server required. PHP is compiled to WebAssembly (PHP-WASM), MySQL is replaced by SQLite, and server functionality is replaced by JavaScript APIs. This means anyone can instantly spin up a WordPress instance in their browser, making it easier than ever to demo plugins or test workflows.

    Real-World Use Cases

    I highlighted two practical use cases during my talk:

    Plugin Demos and Live Previews

    With WordPress Playground, plugin developers like me can offer live previews directly in the browser. For example, if you’re browsing the WordPress.org repository, a plugin could have a “Live Preview” button. Clicking it would launch a full WordPress instance with the plugin activated, allowing users to test it instantly—no setup required.

    Markdown Documentation Editing

    I use WordPress to manage my blog content, but I prefer keeping my documentation in Markdown files close to the codebase. WordPress Playground enables me to bridge the gap between these workflows. I can import Markdown files from a GitHub repository into WordPress running in the browser, make edits using a familiar CMS interface, and export the updated files back to GitHub as a pull request. This workflow combines the strengths of both traditional CMSs and modern version control systems.

    Beyond the Browser

    WordPress Playground isn’t limited to browser-based workflows. It can run in:

    • Terminal applications
    • Native mobile apps
    • Desktop environments
    • Embedded in web pages
    • Edge servers for near-instant content delivery

    This versatility allows WordPress to adapt to countless use cases, redefining how and where it can be used.

    A Call to Action

    WordPress Playground is a free, open-source project that pushes the boundaries of what’s possible with WordPress. Whether you’re a long-time WordPress user or new to the platform, I encourage you to explore how this technology can power your projects or inspire you to build something new. For more information, visit WordPress Playground.

    Thank you to everyone who attended my talk or watched it online. If you’d like to chat more, find me on X/Twitter at @jasonbahl.

  • Try WPGraphQL Instantly with WordPress Playground Integration

    Try WPGraphQL Instantly with WordPress Playground Integration

    We’re excited to announce that WPGraphQL v1.29.2 now supports Live Preview functionality on WordPress.org, powered by WordPress Playground. This integration makes it easier than ever for developers to experience WPGraphQL firsthand without any installation or setup required.

    Instant Access to GraphQL in WordPress

    Starting with version 1.29.2, visitors to the WPGraphQL plugin page on WordPress.org can click the “Live Preview” link to instantly launch a fully functional WordPress environment in their browser.

    This environment comes pre-loaded with WPGraphQL and provides immediate access to the GraphiQL IDE.

    Zero Setup Required

    Thanks to WordPress Playground, trying out WPGraphQL is now as simple as:

    1. Visit the WPGraphQL plugin page on WordPress.org
    2. Click the “Live Preview” link
    3. Start exploring the GraphQL API in your browser

    All you need is a web browser and an internet connection – no local development environment, no plugin installation, and no configuration required.

    Perfect for Quick Evaluation

    This new feature is particularly valuable for:

    • Developers evaluating WPGraphQL for their projects
    • Teams wanting to quickly demonstrate WPGraphQL capabilities
    • Learning and exploring GraphQL queries in a WordPress context
    • Testing compatibility with WordPress core features

    What’s Next?

    While the Live Preview feature provides a great way to explore WPGraphQL’s capabilities, remember that for production use, you’ll want to install WPGraphQL directly on your WordPress site. The Live Preview environment is perfect for testing and exploration, but it’s temporary and resets between sessions.

    We’re excited to see how this new feature helps more developers discover and experiment with WPGraphQL. Give it a try and let us know what you think!

    Have you tried the new Live Preview feature? We’d love to hear your feedback in the WPGraphQL Discord below or on GitHub.

  • WPGraphQL Becomes a Canonical Plugin: My Move to Automattic

    Before diving into the details of this announcement, I want to address something important. I am, like all of you, a human being. Given the current tensions in the WordPress ecosystem, my decision to move from WP Engine to Automattic might evoke strong feelings. Whether you agree or disagree with this decision, please recognize me as a human. Please treat me with respect, even if you strongly oppose my choices. The WordPress community is one I care deeply about, and we all benefit from respectful dialogue, no matter our differences.

    With that said, I’m excited to announce that after 3.5 wonderful years at WP Engine, I’ve accepted an offer with Automattic to continue my work on WPGraphQL as it transitions into becoming a canonical community plugin on WordPress.org.

    Reflecting on My Time at WP Engine

    I’ve truly enjoyed my time at WP Engine. I’ve had the opportunity to publish over 100 releases of WPGraphQL, re-architect WPGraphQL for ACF, introduce WPGraphQL Smart Cache, and help countless users successfully deploy decoupled sites powered by WPGraphQL. I’ve made great friends at WP Engine and hope to continue collaborating with them in the open-source ecosystem for years.

    That said, as someone deeply committed to Free Open Source Software (FOSS), the economics around open-source projects can take time to balance. While WP Engine has treated me well personally, the focus on open-source contributions from the organization has declined during my time there. My time was also reallocated away from WPGraphQL and community projects as internal initiatives took priority. Any company needs to focus on internal growth. Still, I believe there’s a conversation to be had about how that fits into the broader open-source community and whether it supports long-term success. Several other former colleagues and I tried to talk about how WP Engine could better participate in Open Source, but those conversations didn’t always gain traction. Hopefully, those conversations can begin again. I don’t have the answers, but I do know there is a problem.

    Why Automattic? Why Now?

    WPGraphQL has always been and will continue to be free open-source software. Automattic’s track record as a fantastic steward of open-source projects is well known, and I believe it’s the perfect home for WPGraphQL. This move will continue to keep WPGraphQL free and open source while bringing more visibility and contributions from the community.

    There is so much untapped potential in the decoupled WordPress ecosystem. While WPGraphQL is already trusted to power thousands of sites, this move will allow us to make even more progress in helping teams build modern API-driven websites and applications with WordPress. Becoming a canonical community plugin will open up new opportunities for collaboration, growth, and innovation across the ecosystem.

    On Matt Mullenweg’s Recent Actions

    There will likely be assumptions that by joining Automattic, I’m fully endorsing every action Matt Mullenweg has taken recently. This is not the case. I’ve told Matt directly that I don’t agree with everything he’s done — and he has welcomed the disagreement. For example, I don’t think WordCamp US was the right time or place for his speech. I also do not agree with blocking WP Engine customers from WordPress.org without more notice. Should WordPress.org be required to remain a free service forever? Not necessarily. But should long-time users receive advance notice when significant changes are made? I think so.

    I could probably list many other things that I don’t agree with Matt on but the reality is that I’ve never worked at a company where I’ve agreed with every single action their leaders have taken. 

    Leadership often involves making uncomfortable choices that others might not fully understand or agree with. His historical actions have led WordPress to its current success, and I believe that bold moves—though uncomfortable—are sometimes necessary to ensure the long-term future of WordPress. As a maintainer of open-source software, my livelihood depends on people like Matt, who are willing to keep WordPress relevant in the years to come.

    WPGraphQL is becoming a canonical WordPress community plugin

    Automattic has a long record of nurturing open-source projects used by millions. By becoming a canonical project—similar to WP-CLI, Gutenberg, or the WP REST API before it was merged into core—I anticipate a lot of support from Automattic and the wider community. I believe this move will bring tangible benefits not just to WPGraphQL users but also to the hosts and developers building decoupled WordPress experiences.

    There’s much more to come, and I’m excited to continue building tools and features that help teams succeed with modern web development using WordPress and WPGraphQL. Together, we can achieve great things for the entire ecosystem!

  • Migrating the WPGraphQL Slack Community to Discord

    Hello WPGraphQL Community,

    We’re excited to announce that we’re moving from Slack to Discord! This change will enhance our communication and community experience.

    📣 Why Move to Discord?

    No More Lost History: All message history from Slack (since 2017!) has been migrated and is searchable in Discord.
    Dedicated Channels: Specific topics for streamlined conversations.
    Voice Channels: Engage with others directly through voice chats.
    Community Events: Stay updated on upcoming events, webinars, and more.
    Enhanced Moderation: Keeping the community safe and welcoming.
    Resource Sharing: More tools for organizing content and sharing ideas.

    💬 Join Us on Discord!

    • Download Discord (desktop, mobile) or use in the browser.
    • Click this invite link: https://discord.gg/AGVBqqyaUY
    • Introduce yourself in #introductions channel and start exploring!

    Let’s make this move together and continue growing the WPGraphQL community!

    Best,

    Jason Bahl
    Creator and Maintainer of WPGraphQL

  • Announcing the WPGraphQL REPL

    “What is a REPL?”, “Who are you?”, and “What have you done with Jason?” are all good questions you might be asking. I will start with the most important one. Hello, I am Alex aka “moonmeister”! I have been around for a while and you might have seen me in Slack or chatted with me when I worked at Gatsby or WP Engine. I recently started wpdecoupled.dev where I write about all things decoupled/headless WordPress. I mostly work on the JavaScript side of code and leave the PHP to folks like Jason Bahl and David Levine.

    I am happy to announce the initial release of the WPGraphQL REPL. In this post, I will be talking about what it is I built and why I built it.

    TL;DR

    I built a REPL for WPGraphQL. A REPL helps us accelerate learning, bug finding, and more by allowing you to spin up a working WP instance in the time it takes you to load a web page. You can find it at repl.wpgraphql.com. Use it, love it, share it. There are lots of features yet to build and bugs to find. Go wild, and come help build a better future on the repo.

    What’s a REPL?

    For those who are not familiar, a REPL (Read-Evaluate-Print Loop) is a really valuable tool for any ecosystem. A REPL can be used to reproduce a bug, teach the basics of the ecosystem, experiment, and more quickly collaborate. Still confused? Let’s dig deeper!

    Bugs

    Okay, you are building with WPGraphQL and something is not working, you have found a bug. You move from your JavaScript client to GraphiQL in the WP Admin. You see the bug happening there too. You now know not to blame JavaScript. What do you do next? My next step is to replicate the bug in a “minimal reproduction”.

    Get it? REPL…replicate…it is an acronym and an abbreviation!

    The idea of a minimal reproduction is to eliminate variables. No, not the let foo = "bar"; kind. What PHP, WP, and WPGraphQL are you running? What other plugins are installed and what are their versions? These are all questions that help us track down the source of an issue. The reason maintainers often ask folks to create their own minimal reproductions is the act of doing so helps folks break down an issue, eliminate variables, and solve their own problem.

    Given the numerous versions of PHP, WP, and WPGraphQL this can be very time-consuming. Usually, PHP and WP versions can be ignored, but not always. Luckily, we have had Local for years which helps accelerate this process, but it is still quite time-consuming. Inevitably, I end up cowboy coding on my production instance cause it is just faster.

    This is where a REPL comes in. If I have a place I can quickly get WP running with WPGraphQL and switch between a variety of versions and test code on the fly, I am going to get to a minimal reproduction and an answer faster.

    Experimenting

    I have often run into situations where I want to try a new plugin, or just delve into an aspect of WPGraphQL I am not super familiar with. GraphiQL in my WP instance can be helpful here. But once again it is slow to spin up WP, even in Local. I just want something fast so that I can grab the one plugin I need and GO! I want to get back to the building by accelerating the learning process.

    Learning/Teaching

    There are many situations where I need to share the code with others. This could be and embed in a blog post or just a quick reply to someone trying to figure out WPGraphQL in Slack. Either way, I want a fast and controlled way to write code and hand it to them in a way they can see, understand and start their own experimentation.

    Are you seeing the theme…speed. This is what REPLs provide us…it gets us away from “it works on my machine”…it gets us away from Docker hell…it gets us to what we really need, a reproducible and flexible environment where I can focus on my specific issue and not worry about my LAMP stack, breaking production, or anything other than the issue at hand.

    My Dream Realized

    For as long as I can remember, I have wanted a REPL for the WPGraphQL ecosystem. I knew it was theoretically possible but practically, I did not have the skills to implement it. Then I saw an announcement from the WordPress community on https://developer.wordpress.org/playground/.

    My dream was possible. I no longer needed to learn how to run PHP and WP in WASM, I could just build the UI and control interface to the specific needs of the WPGraphQL community. After a couple of 4 am coding sessions, I had something I could conceive of sharing. Several weeks of random coding sessions later and an initial release is here.

    Getting Started

    After navigating to https://repl.wpgraphql.com WP will load within ~20 seconds. First to load will be the familiar GraphiQL instance that comes with WPGraphQL. On the left panel, you are currently able to navigate to a new URL and change the running PHP and WP versions.

    Currently, the state (db and filesystem) within WP is ephemeral and will be lost with a page load. Work is being done by the WordPress Playground team to persist the state across refresh. If you want to save your state or load your configured WP into a LAMP stack outside of the browser you can use the download button in the upper right to download a zip of your site. I hope to have an upload button soon to be able to reload that same file back in later.

    Please, go check out https://repl.wpgraphql.com, I hope you come to value a good REPL as much as I do. Enjoy! If you run into missing features or bugs please head over to the Github repo and open issues, request features, and contribute code to make this better! We also have a #repl channel on the WPGraphQL Slack!

  • Customizing GraphQL Cache Keys.

    WPGraphQL Smart Cache is quickly becoming the standard solution for fast and accurate data when using WPGraphQL for decoupled applications. Since launching in December 2022, it’s grown to 500+ active users!

    While it solves a lot of problems for a lot of users, it’s not perfect and might require customization.

    In this blog post, we’re going to look at how to customize the keys that are returned with GraphQL responses, which customizes how the GraphQL documents are tagged in the cache, and thus customizes what events will purge the cached document.

    How WPGraphQL Smart Cache Invalidation works

    Before we dive into customizing WPGraphQL Smart Cache keys, let’s take a look at how caching and cache invalidation with WPGraphQL Smart Cache works.

    Understanding how GraphQL Queries are Cached and “Tagged”

    When making a query to a WPGraphQL-powered endpoint, WPGraphQL will return headers that caching clients can use to tag the cached document with.

    To see this in action, I will use a local WordPress install (powered by Local). In this WordPress install, I have the following plugins installed and activated:

    In the WordPress dashboard, I will navigate to the GraphiQL IDE.

    I will open Chrome’s dev tools and select the “Network” tab.

    Then, in the GraphiQL IDE, I will execute the following query:

    query GetPosts {
      posts {
        nodes {
          title
          uri
        }
      }
    }

    And I see the following response:

    Screenshot of the GraphiQL IDE executing a query for posts and showing the JSON response from the query.

    With the Network tools open, we can click on the request and inspect the headers:

    Here, we see the X-GraphQL-Keys header with a list of keys. If this query were made via a GET request to a site hosted on a host that supports it, the response would be cached and “tagged” with these keys.
    For this particular query, we see the following keys:

    • 4382426a7bebd62479da59a06d90ceb12e02967d342afb7518632e26b95acc6f (hash of the query)
    • graphql:Query (operation type)
    • operation:GetPosts (operation name)
    • list:post (identifies the query asked for a list of posts)
    • cG9zdDox (id of the node(s) resolving. In this query response, only 1 node was resolved)

    The document will be tagged with these keys, and in turn will be purged (deleted) from the cache if a purge event for one of those tags is triggered.

    Understanding Cache Invalidation with WPGraphQL Smart Cache

    Above, we looked at how supported hosts will cache GraphQL responses and use the X-GraphQL-Keys to “tag” the cached document.

    Now let’s take a look at how WPGraphQL Smart Cache invalidates, or “purges” these tagged documents from the cache.

    WPGraphQL Smart Cache listens to events that occur in WordPress, and in response to these events, calls “purge” on specific “tags”, deleting any document from the cache that was tagged with said tag.

    The simplified summary of the WPGraphQL Smart Cache invalidation strategy is as follows:

    • Publish events call purge( 'list:$type_name' )
    • Update events call purge( '$nodeId' )
    • Delete events call purge( '$nodeId' )

    How Cache Invalidation and Cache Tags work together

    Now that we have an idea of how cached documents are tagged, and how events in WordPress call “purge” on different tags, let’s bring it all together.

    Above we identified the query keys that the document will be tagged with. And now that we understand the cache invalidation strategy, we know that the GetPosts query will be purged from the cache whenever the following events occur:

    • A new post is published ( purge( 'list:post' ) )
    • The node identified by id cG9zdDox (the “hello world” post) is updated or deleted
    • Clicking “purge cache” in the GraphQL > Settings > Cache page (`purge( ‘graphql:Query’ )` )
    • Any purge event manually added to purge based on operation name or query hash

    So far, so good! This all seems reasonable. I think we would probably all want the cache for this query to be invalidated after we updated the “Hello World” post. We would want to see the updated data in the query response.

    The Problem

    The problem, however, is that the headers that are added to the documents might be more broad than we would like, and we might need to customize this.

    For example, let’s take a look at a more complicated query:

    query GetPostsWithCategoriesAndTags {
      posts {
        nodes {
          id
          title
          categories {
            nodes {
              id
              name
            }
          }
          tags {
            nodes {
              id
              name
            }
          }
        }
      }
    }

    In this query, we’ve asked for a list of posts, a list of categories belonging to each post and a list of tags belonging to each post.

    In the response, we see that we have Posts, categories and tags (only 1 of each in this case, as we’re on a simple test site with minimal data). And if we inspect the X-GraphQL-Keys header, we will see that it’s tagged with list:post, list:category and list:tag. This is because we asked for each of these types of nodes and when a new post, category or tag is made public, it could be part of the list, so we invalidate this cache. And like magic, we could query this again and get a Cache Miss and see fresh content, like the newly published post.

    This all sounds good still, but there is a problem.

    The problem is that the list:category and list:tag keys will cause this document to be purged a lot more than it should be.

    For example, creating a new tag and assigning it to a post that’s not shown in this query’s results will trigger the purge( 'list:tag' ) and invalidate this query, leading to more cache invalidations than we probably want.

    Ideally WPGraphQL and WPGraphQL Smart Cache will be able to better identify when / when not to output the list:$type keys, but for now this is how things work, but there are ways to override it for your specific needs.

    Filtering the X-GraphQL-Keys

    If we want the GetPostsWithCategoriesAndTags query to NOT output the list:tag and list:category keys, we can filter the keys like so:

    // Filter the keys that are returned by the Query Analyzer
    add_filter( 'graphql_query_analyzer_graphql_keys', function( $graphql_keys, $return_keys, $skipped_keys, $return_keys_array, $skipped_keys_array ) {
     
            // Convert the keys from a string to an array
    	$keys_array = explode( ' ', $return_keys );
    
            // Only apply the filter to the "GetPostsWithCategoriesAndTags" query
    	if ( empty( $keys_array ) || ! in_array( 'operation:GetPostsWithCategoriesAndTags', $keys_array, true )  ) {
    		return $graphql_keys;
    	}
    
            // Remove the "list:tag" key from the headers
    	if ( ( $key = array_search('list:tag', $keys_array ) ) !== false ) {
    		unset( $keys_array[$key] );
    	}
    
            // Remove the "list:category" key from the headers
    	if ( ( $key = array_search('list:category', $keys_array ) ) !== false) {
    		unset( $keys_array[$key] );
    	}
    
            // Convert the array of keys back to a space separated string
    	$graphql_keys['keys'] = implode( ' ', $keys_array );
    	
            // Return the "filtered" $graphql_keys
    	return $graphql_keys;
    
    }, 10, 5 );

    In the snippet above, we target a specific query with the operation name “GetPostsWithCategoriesAndTags” and for that query we remove the list:tag and list:category keys from being returned.

    Now, we can execute the same query and inspect the headers, and we will see that list:tag and list:category are both no longer output in the X-GraphQL-Keys header.

    This means that publishing new categories and tags, which triggers purge( 'list:category' ) and purge( 'list:tag' ) will not purge this document.

    Success!

    Now we’re getting the benefits of cached GraphQL documents, and we’re getting the document invalidated when the post is updated or deleted, but we’re letting the cache remain cached when categories or tags are created.

    Conclusion

    While we ultimately believe WPGraphQL Smart Cache should be, well, smarter, it might take some time to find that perfect solution that works for everyone.

    In the mean time, using filters like demonstrated above, can help you tailor your WPGraphQL cache tagging and invalidation strategy to fit your specific project’s needs.