Introduction
Most of us are used to REST when working with Liferay’s APIs. However, REST can occasionally feel restrictive; you may end up making several calls to obtain relevant information or over-fetching unnecessary data. GraphQL can help with that. It allows you the freedom to make a single request for precisely what you need.
Developers can immediately utilize Liferay’s built-in GraphQL support to retrieve content, user information, or even custom object entries. I’ll explain how GraphQL works with Liferay in this tutorial, along with how to run queries and mutations and some pointers for experimenting and expanding it for your own applications.
Prerequisites :
Liferay DXP/Portal 7.X
Proper Knowledge about Liferay’s Headless APIs
Environmental Requirements :
Liferay Portal or DXP
Java
Why use GraphQL with Liferay?
Integrated Access to Data :
Instead of using multiple REST endpoints, GraphQL enables you to query various Liferay APIs (headless APIs, custom services, or objects) using a single endpoint.
Get only what you require :
In order to reduce payload size and improve speed for mobile and web apps, clients can specify which fields to retrieve (for instance, just the name and email of a User object).
Flexibility similar to real-time :
Live updates or real-time use cases on top of Liferay data are made possible by the structure created by GraphQL queries, mutations, and subscriptions.
Better Developer Experience :
Developers can easily explore and consume Liferay data thanks to the robustly typed schema and automatically generated documentation (created with introspection tools like GraphiQL or Apollo Studio).
Endpoint with a single version :
Long-term maintenance is made easier with GraphQL since it enables schema evolution without affecting current clients, unlike REST APIs where versioning becomes complicated.
Effective Data Aggregation :
Perfect for situations where your front end requires information from several Liferay objects in a single round-trip, such as merging users, assets, and categories.
Enhanced Frontend Performance :
minimizes network requests by reducing over-fetching and under-fetching, which is essential for headless implementations or high-performance Liferay sites.
More Suitable for Modern Architectures :
seamlessly integrates with mobile apps and SPA frameworks (React, Angular, and Vue), which are becoming more and more popular for Liferay-based solutions.
Custom Business Logic Support :
You can expose your own domain-specific operations in addition to Liferay’s built-in ones by extending its GraphQL endpoints (either through custom services or JAX-RS GraphQL).
API Layer for the Future :
As the platform’s support for GraphQL advances, implementing Liferay DXP early keeps you up to date with upcoming features and industry best practices.
Headless APIs vs. GraphQL in Liferay
When working with Liferay, you often need to fetch related data spread across different entities. Both Headless APIs and GraphQL can do the job, but the way they handle it is very different. Let’s look at a practical example: fetching categories from a site.
Using Headless APIs
With REST-style Headless APIs, you usually have to make multiple calls to get to the final data:
- Get Site ID (from friendly URL path)
GET
http://localhost:8080/o/headless-admin-user/v1.0/sites/by-friendly-url-path/ignek-blog-site
//Output: 715296
- Get Vocabulary ID (from Site ID)
GET
http://localhost:8080/o/headless-admin-taxonomy/v1.0/sites/715296/taxonomy-vocabularies
//Output: 715629
- Get Categories from Vocabulary
GET http://localhost:8080/o/headless-admin-taxonomy/v1.0/taxonomy-vocabularies/715629/taxonomy-categories
- Get Subcategories from Category
GET http://localhost:8080/o/headless-admin-taxonomy/v1.0/taxonomy-categories/715630/taxonomy-categories
As you can see, this requires chaining multiple requests and handling intermediate responses manually (Site ID → Vocabulary ID → Categories).
Using GraphQL
With GraphQL, the same result can be achieved in a single query:
{
taxonomyVocabularies(siteKey: "ignek-blog-site", filter: "name eq 'IGNEK_VOCABULARY'") {
items {
id
name
taxonomyCategories {
items {
id
name
}
}
}
}
}
Here’s what’s happening :
- You directly query the site using its friendly URL key (ignek-blog-site).
- You filter vocabularies to fetch only “IGNEK_VOCABULARY”.
- You immediately pull back its categories (and could even nest subcategories if needed).
Instead of four separate API calls, GraphQL collapses everything into one network request with a clean JSON response.
Conclusion
- Headless APIs → Great for direct, resource-based calls but can lead to multiple round-trips for related data.
- GraphQL → Best when you need nested or related data in a single request, reducing overhead and making client code much simpler.


