Liferay

Liferay Client Extensions: The future of Liferay development

Hardik Gajjar
Hardik GajjarApr 23, 2026

Introduction

Liferay Client Extensions are transforming how modern Liferay development is done. For years, customization relied on OSGi modules powerful but tightly coupled and difficult to scale.

Today, enterprises demand cloud-native, flexible, and upgrade-safe solutions. This is where Client Extensions come in enabling external, API-driven, and independently deployable architectures that align with Liferay headless development principles.

Why Client Extensions matter now

For years, Liferay customization meant one thing, OSGi modules. You wrote Java bundles, deployed them to the server, and hoped your customizations survived the next upgrade cycle.

That model worked. Until it didn't.

As enterprises demanded faster deployments, cloud-native architectures, and decoupled frontends, the OSGi approach started showing its age. Upgrades became risky. Deployments were heavy. Every customization was tightly coupled to the platform version underneath it.

Liferay's answer? Client Extensions Liferay teams rely on today. Not a patch, a fundamental shift in how Liferay headless development is done. In 2026, it's no longer the future. It's the standard.

What are Client Extensions?

Client Extensions are external, independently deployable applications or configurations that extend Liferay without modifying its core. They live outside the Liferay container, communicating via REST/GraphQL APIs, webhooks (for event-driven flows), and secured using OAuth2.

This decoupled approach is the foundation of modern Liferay headless development, your extensions are fully independent from the platform's internals and only interact through stable, versioned APIs.

Old OSGi way

  • Code lives inside Liferay's container
  • Tightly coupled to internal APIs
  • Upgrades break customizations
  • Full redeployment for every change

Client Extensions way

  • Code lives outside Liferay
  • Communicates via stable, versioned APIs
  • Upgrade-safe (API dependent)
  • Deploy, update, roll back independently

Types of Client Extensions

Client Extensions Liferay fall into four broad categories. Each serves a different layer of your Liferay implementation.

1. Frontend Client Extensions

These control what users see - themes, styles, JavaScript behavior, and custom UI components.

Types :

TypeWhat It Does
CSS Client ExtensionInject custom CSS into Liferay pages
Theme CSS Client ExtensionReplace Liferay's default theme styles entirely
JS Client ExtensionAdd custom JavaScript without touching Liferay's core JS
Static Content Client ExtensionServe static assets (images, fonts, files) from an external CDN or server
Theme Favicon Client ExtensionOverride the default favicon per site
Theme Spritemap Client ExtensionReplace Liferay's default spritemap with a custom icon set
Custom Element Client ExtensionRegister a web component (React, Angular, Vue) as a Liferay widget
IFrame Client ExtensionEmbed an external application inside a Liferay page
Frontend Data Set Filter Client ExtensionAdd custom filter options to Liferay's Frontend Data Set component
Frontend Data Set Cell Renderer Client ExtensionCustomize how individual cells render inside a Frontend Data Set
Editor Config Contributor Client ExtensionCustomize the rich text editor configuration across your instance
JS Import Maps Entry Client ExtensionAdd entries to the browser's import map for module resolution

Example : Registering a React component as a Liferay widget :

1# client-extension.yaml
2assemble:
3  - from: build/static
4clientExtensions:
5  my-react-widget:
6    cssURLs:
7      - index.*.css
8    friendlyURLMapping: my-react-widget
9    htmlElementName: my-react-widget
10    name: My React Widget
11    type: customElement
12    urls:
13      - index.*.js
14    useESM: true

2. Microservice Client Extensions

These provide API endpoints that Liferay can trigger - object actions, workflow steps, notification events, with the actual logic running outside Liferay as a standalone microservice. Your service can be written in any language.

The Liferay microservices architecture built around this CE type lets you run each piece of business logic independently, no Liferay restart, no re-deployment of the whole platform, no shared JVM risk.

Types :

TypeWhat It Does
Object Action Client ExtensionRun custom logic when a Liferay Object record is created, updated, or deleted
Object Validation Client ExtensionAdd custom validation rules to Liferay Objects before a record is saved
Workflow Action Client ExtensionTrigger external logic at a specific step in a Liferay workflow
Notification Type Client ExtensionCreate custom notification delivery channels beyond the defaults
Captcha Client Extension Integrate external CAPTCHA providers to validate user interactions and prevent automated or bot submissions

Example : Notification Type triggering an external microservice :

1assemble:
2    	- fromTask: bootJar
3
4my-oauth-user-agent:
5.serviceAddress: localhost:58081
6.serviceScheme: http
7name: My OAuth User Agent
8Scopes:
9   - Liferay.Headless.Admin.Workflow.everything
10type: oAuthApplicationUserAgent
11

When a Liferay Object record is saved, Liferay sends a POST request to your external service at /sync-to-crm, authenticated via OAuth2. Your service can be in Node.js, Python, Go, anything.

Going deeper into Microservice CEs? We have a dedicated blog covering the full Liferay microservices architecture , OAuth2 flow, and real implementation with Spring Boot : Microservice Client Extension in Liferay

3. Batch Client Extensions

Batch Client Extensions provide data entities to your Liferay instance, things like object definitions, workflow definitions, and other structured data. They work via Liferay's batch engine framework and are particularly useful for moving configurations between environments without manual re-setup.

Types :

TypeWhat It Does
Batch Client ExtensionImport or export structured data entities (object definitions, workflow definitions) via Liferay's batch engine

Example : Batch Client Extension for importing object definitions :

1# client-extension.yaml
2assemble:
3  - from: batch
4    include: "**/*"
5    into: batch
6clientExtensions:
7  my-batch-client-extension:
8    name: My Batch Client Extension
9    oAuth2ApplicationExternalReferenceCode: my-oauth-app
10    type: batch

The exported *.batch-engine-data.json files (in jsont format) go into the batch/ directory. When deployed, Liferay's batch engine reads and imports them automatically into the target instance.

Batch Client Extensions can be grouped with Configuration Client Extensions in the same project, since both represent configuration-type workloads rather than running services.

4. Configuration Client Extensions

These provide specific configurations to change functionality within your Liferay instance. They can be combined with other Client Extension types, for example, pairing an OAuth User Agent CE with a Microservice CE to handle authentication for user-triggered events.

In Liferay SaaS development, Configuration Client Extensions are especially important — since you can't touch the server directly, deploying configurations as code is the standard way to manage instance-level settings.

Types :

TypeWhat It Does
OAuth User Agent Client ExtensionRegister an OAuth2 application for user-facing flows
OAuth Headless Server Client ExtensionRegister an OAuth2 application for server-to-server flows
Instance Settings Client Extension Configure a wide variety of Liferay instance settings via their PID (Persistent IDentity), deployable as code

OSGi vs Client Extensions : Which One Should You Use?

The Liferay OSGi vs Client Extensions debate is the question that matters most for teams making architectural decisions. Both can extend the platform, but they take fundamentally different approaches, and choosing the wrong one creates long-term pain.

FactorOSGi ModulesClient Extensions
ArchitectureRuns inside Liferay's JVM, tightly coupled to the platformRuns outside Liferay, communicates via headless APIs
LanguageJava onlyAny language, Node.js, Python, Go, Spring Boot, React
Development ComplexityHigh, requires deep OSGi and Liferay internals knowledgeLower, YAML config or standalone app, no OSGi knowledge needed
DeploymentBundled JARs deployed into Liferay runtimeIndependent service or Docker container, deployed separately
Upgrade SafetyRisky, internal API changes often break modulesSafe, depends only on stable headless APIs
ScalabilityScales only with the entire Liferay serverScales independently like any microservice
Cloud ReadinessLimited, not suitable for Liferay SaaSFully cloud-ready — the only option for Liferay SaaS development
Fault IsolationA faulty module can impact the whole serverA faulty extension doesn't affect Liferay's core
Best ForDeep platform customizations, core service modificationsExternal integrations, frontend widgets, decoupled logic

When to still use OSGi : If you need direct access to Liferay's internal services, complex Service Builder modules, or deep hooks into core platform behavior, OSGi is still the right tool. Client Extensions Liferay can't replace everything.

For everything else : Client Extensions are the recommended path, simpler, safer, and future-proof. This is especially true for teams moving toward Liferay headless development or working in Liferay SaaS environments.

Want the full breakdown? We've covered the Liferay OSGi vs Client Extensions comparison in detail - architecture, deployment, scalability, and real use cases, in a dedicated blog: Comparison of Client Extensions and OSGi: Modern vs Traditional Liferay Development

Real-World Use Cases

Client Extensions Liferay enterprises adopt are solving real problems, not just developer convenience.

1. Multi-brand theming without forking A global enterprise runs 5 brand sites on one Liferay instance. Instead of forking themes or managing separate deployments, they use Theme CSS Client Extensions, one per brand, each deployed independently, each overriding only what needs to change.

2. Liferay Objects + external CRM sync A sales portal built on Liferay Objects needs to sync leads to Salesforce in real time. An Object Action Client Extension fires on every record creation, sending a webhook to a Node.js microservice that handles the Salesforce API call. Liferay never touches Salesforce directly. A clean example of Liferay microservices architecture in practice.

3. React microfrontend inside Liferay A team already has a React dashboard they've built separately. Instead of rebuilding it inside Liferay, they register it as a Custom Element Client Extension. It lives in their own CI/CD pipeline, gets deployed independently, and appears as a draggable widget in Liferay's page editor, pure Liferay headless development thinking.

4. AI-powered content validation An Object Validation Client Extension calls an external AI service to check whether user-submitted content meets brand guidelines before saving - without any core Liferay modification.

Getting Started : Your First Client Extension

Here's the minimum you need to get a Client Extension running locally.

Prerequisites :

  • Liferay DXP (latest) running locally or via Docker
  • Node.js 18+
  • Liferay CLI (@liferay/cli)

Step 1 : Create a workspace :

1liferay init client-extension-workspace
2cd client-extension-workspace

Step 2 : Pick a sample :

1liferay add
2# Select a Client Extension template

Step 3 : Configure client-extension.yaml :

Every Client Extension is defined by this file. It tells Liferay what type of extension this is, where to find its assets, and how to connect to it.

1clientExtensions:
2  my-global-css:
3    name: My Global CSS
4    type: globalCSS
5    url: ./css/custom.css

Step 4 : Deploy :

1./gradlew deploy

Liferay picks it up automatically. No server restart needed.

Final Thought

Client Extensions aren't just a new API, they represent a philosophy shift. Liferay is moving toward a world where the platform is the stable core, and everything built on top of it is independently deployable, independently scalable, and upgrade-safe by design.

Whether you're exploring Liferay SaaS development, building a Liferay microservices architecture, or simply trying to move away from OSGi, Client Extensions are the direction the platform is heading.

For development teams, that's not a constraint. That's freedom.

FAQs

1. Can I still use OSGi modules in 2026? Yes, OSGi modules aren't removed. But for most use cases, Client Extensions Liferay developers now prefer are the recommended approach. OSGi makes more sense for deep platform customizations that can't be achieved externally.

2. What languages can I use for backend Client Extensions? Any language that can run an HTTP server, Node.js, Python, Go, Java, .NET. This language-agnostic flexibility is one of the biggest advantages of the Liferay microservices architecture that Client Extensions enable.

3. Are Client Extensions supported on Liferay SaaS? Yes. In fact, Client Extensions are the primary and recommended way to extend Liferay SaaS, since you can't deploy OSGi modules to a managed cloud environment. Liferay SaaS development is built around this model.

4. How does authentication work between Liferay and my Client Extension? Via OAuth2. Liferay sends authenticated requests to your service using tokens. You configure this through OAuth Client Extensions in your client-extension.yaml, a core part of Liferay headless development patterns.

5. Do Client Extensions affect Liferay's upgrade path? No, that's the whole point. Since your code lives outside Liferay, upgrades don't touch it. The Liferay OSGi vs Client Extensions question often comes down to exactly this, upgrade safety is one of the strongest reasons teams are making the switch.

© 2026 IGNEK. All rights reserved.

Ignek on LinkedInIgnek on InstagramIgnek on FacebookIgnek on YouTubeIgnek on X