AEM and GraphQL Playground for Testing Content Queries

Adobe Experience Manager has quietly become one of the most capable headless content platforms in the enterprise space, and the GraphQL layer shipped with AEM 6.5 and refined in subsequent releases sits at the heart of that shift. For developers building consumer experiences on top of AEM, the GraphQL Playground is the place where authored content stops being a static promise and becomes something you can actually interrogate. You craft a query against a Content Fragment model, fire it off, and within a second or two you have JSON in your editor that mirrors what a SPA, a mobile app, or a partner integration would eventually consume.

In Australia, this headless momentum is particularly visible in Sydney and Melbourne, where financial services firms, retailers, and government agencies have spent the last few years decoupling their web properties from legacy CMSs. The pattern is familiar: content lives in AEM as structured fragments, and GraphQL becomes the lingua franca between the editorial team and a fleet of digital channels that range from a public website to an in-store kiosk in a Westfield shopping centre. The Playground gives those teams a shared vocabulary and a shared sandbox, which is half the battle when architects, Java developers, and front-end engineers sit in different time zones across AEDT and AWST.

The Playground is not just a developer toy. It packages schema introspection, query history, variables, headers, and a response panel into one tab, so a Java developer configuring an OSGi service and a front-end developer wiring up a Next.js build can look at the exact same screen and reason about the same data contract. That kind of alignment matters in places like Brisbane's fintech corridor, where teams routinely ship AEM-backed content into regulated mobile apps that need to render reliably across both Australian and offshore markets.

Treating the Playground as a contract-design surface rather than a production tool is the right mental model. The response you see there is clean and synchronous, with no dispatcher cache to confuse things and no CDN edge to round-trip through. Once you start hitting a real endpoint behind a CDN in Sydney or a CDN in Singapore, behaviour shifts, and that is where richer testing takes over.

Enabling the GraphQL Endpoint in AEM

Before the Playground is useful, the AEM instance itself needs to be configured to serve GraphQL traffic. That starts with the GraphQL Servlet and Servlet Helper service in the OSGi console, which exposes a /content/cq:graphql/<config>/endpoint.json path once enabled. On a clean author instance, this is usually a matter of checking a box, but on heavily customised deployments the servlet may sit behind a dispatcher rule that strips query parameters or rewrites paths in unexpected ways.

Sydney-based retailers with multi-region content trees often run into trouble here because their dispatcher configurations were originally written for traditional HTML pages. A GraphQL request carrying a complex query string can be silently blocked, and the developer is left wondering why the Playground returns results while the same query through the dispatch layer returns a 404. The fix is usually a small change to the dispatcher farm file, but the diagnosis is much faster when you can confirm in the Playground that the underlying AEM endpoint is healthy in the first place.

Once the endpoint is reachable, the next step is exposing Content Fragment models. AEM auto-generates a GraphQL schema from any model under /conf/<project>/settings/dam/cfm/models, and the Playground's schema panel will populate as soon as you point it at the right config path. If a model does not appear, the cause is almost always either a permissions issue or a model that has not yet been enabled for GraphQL, both of which can be confirmed in the fragment model editor without leaving the browser.

Inside the Playground Interface

Open the Playground for the first time and the screen splits into three regions: the schema explorer on the left, the query editor on top, and the response viewer on the bottom. The schema explorer is generated dynamically from the AEM endpoint, which means it always reflects what AEM is actually willing to serve. That is a quiet but important guarantee, because Content Fragment models evolve and a stale schema is the fastest way to ship broken queries.

Most developers pick up the keyboard shortcuts within an afternoon. Prettify cleans up a sprawling query, merge inlines fragments, and the auto-complete on Ctrl-Space leans on the live schema rather than a cached copy. Variables can be declared in a dedicated pane and passed into a query, which is the right pattern for anything beyond a simple lookup. A query that filters by category and paginates with offset and limit is far easier to reason about when category and pageNumber are variables rather than hard-coded strings buried in the body.

Melbourne-based digital agencies that build storefronts for local fashion brands tend to push the Playground hard because their content models carry nested references: a Product fragment references a Collection, which references a Lookbook, which references assets. Walking that tree through the explorer before writing a single line of code is the cheapest way to discover that a field you assumed was required is actually optional, or that a reference resolves to a fragment of a different model entirely.

Querying Content Fragments with Confidence

A well-formed AEM GraphQL query reads almost like a sentence. You name the model, list the fields, and add filters, sorting, and pagination as clauses. Filters use a simple _<field>: syntax, sorting uses sort, and pagination combines offset with limit or uses cursor-based paging if the model supports it. The Playground makes it trivial to add these clauses one at a time and watch the response contract shrink or grow.

References are where queries get interesting. A query that returns a Brand fragment alongside its Store Locations fragment resolves nested data in a single round trip, which is a major improvement over the REST era where developers would chain requests together and pray that nothing changed between calls. In the Playground you can confirm that the nested resolution actually populates, that image references resolve to _path and _publishUrl, and that text fields render with the multiline variants the author intended.

Variables turn a working query into a reusable one. By parameterising locale and region, a developer in Adelaide can hit the same AEM endpoint that a colleague in Perth hits, just with different inputs. This is also where teams start to think about persisted queries, because a query that is parameterised but otherwise static is a prime candidate for being baked into a configuration file and pushed through a CDN. For groups that want to formalise this further, customising the AEM workflow dashboard to expose GraphQL test runs alongside content approvals is a worthwhile investment, and the CIRCUIT write-up on operational efficiency dashboards walks through how to wire query validation into the editorial flow.

Debugging and Validating Responses

A Playground response that looks correct can still be subtly wrong. The most common issue is a field type mismatch: an author populates a single-line text field with a long description, and the JSON truncates at the first newline. The Playground will not warn you about this; you have to notice it. Reading responses with the JSON viewer set to raw, or piping them through jq after exporting, surfaces these problems quickly.

Null references are another quiet source of bugs. A query that asks for brand { logo { _path } } will return null for logo if the reference is empty, and downstream code that does not handle null will crash. The Playground makes it obvious which paths are nullable because the explorer tags them, and a quick test query that intentionally omits a reference confirms that the rest of the response still resolves.

Performance is the third axis worth watching. GraphQL makes it easy to write a query that returns more data than it needs, and AEM will happily oblige. N+1 problems can creep in when a query iterates a list and resolves a nested reference per item. The Playground's response time is a rough proxy: a query that takes more than a second locally is usually asking for too much, and the fix is often as simple as pruning a field the consumer does not actually render.

Taking Queries Beyond the Playground

Once a query is solid, the next step is persistence. AEM supports persisted queries via the /graphql/persist.json endpoint, which lets you register a query under a slug and call it without sending the body on every request. Persisted queries are faster, easier to cache, and harder for a third party to abuse, which is why most production AEM sites eventually route all traffic through them.

From there, the Playground hands off to integration tests. Snapshot tests that compare a Playground response to a production response under known inputs catch schema drift early. Running those tests against a stage environment in a different geographic region, say a Singapore edge to mirror production conditions for Australian users, gives an honest read on latency and cache behaviour.

Teams that treat the GraphQL Playground as a starting point rather than a destination tend to ship faster. The combination of a well-modelled AEM instance, a disciplined query design, and a CI pipeline that enforces both is what separates a prototype from a production-grade headless AEM implementation.

The conversations that turn these patterns into habits are the ones that happen in person, and CIRCUIT has long been the gathering for AEM practitioners who want to trade war stories with their peers. Registration is open now, and seats tend to move quickly once the agenda lands.