New Blog Post: Customization is Dead! Long Live Customization!

https://liferay.dev/blogs/-/blogs/customization-is-dead-long-live-customization

For the last few years, we’ve been emphasizing client extensions as the modern, upgrade-friendly way to extend Liferay. They live outside the platform, rely on stable Headless APIs, and make upgrades dramatically easier.

But somewhere along the way, that message sometimes got interpreted as:

“Don’t customize Liferay anymore.”

That’s not the case. In the blog, I dig into what the “use client extensions” message really means — and why customization is still alive and well. Liferay still fully supports OSGi modules, Service Builder, REST Builder, the asset framework, and all the tools that let you extend deeply when you need to.

The key is balance — understanding when to use client extensions for low upgrade cost, and when deep customization still makes sense.

So I’m curious…
:backhand_index_pointing_right: Did our messaging make it sound like we were saying “don’t customize”?
:backhand_index_pointing_right: Or am I just reading too much into it?

Would love to hear your thoughts in the comments.

4 Likes

Actually, this rings quite a bell. We had a lot of discussions in the last couple of months with Liferay and we were always told: Use client extensions. Whatever the problem, use client extensions.

Client extensions would have, in a lot of cases, added quite the complexity to the current setup. When you need to do backend code (e.g. for data validation and preparation), you can’t implement it in Javascript. Adding a docker container, implementing those rest calls to fetch everything from Liferay, … can obviously be done. Could have been an option if we had started from scratch. But on our codebase? Why should we?

On the backend we already have a lot of custom code and several rest services, adding a new one is trivial.
We explained this several times, but still, a Liferay consultant told us on every question: Use client extensions.

A second point was in regards to Objects. It was decided in the project to use Objects quite heavily. Using Objects has some clear advantages, but we also found quite some disadvantages. But that’s a huge topic and we knew from the beginning that it will be a tradeoff.

Relating to this topic, some Objects store “secret data” used only on the backend, so permissions are quite restrictive, admin only. Users should never see those Objects directly. We use the Objects in OSGI rest services to provide data for the enduser.

The bad thing is, we found that ObjectEntryLocalService checks permissions in some cases. A clear breach of contract, LocalServices should not do that. So we asked about that, the answer from the project team was: You should not user ObjectEntryLocalService. You should use only the rest services.

We worked around the issues, but basically one could argue that the conclusion is: If you implement stuff in Liferay backend with OSGI, don’t use Objects. Use Objects only with client extensions. Which would be a bit sad.

———-
So, the tldr is: The message I (and several other people) hear from Liferay is: Move away from extending Liferay. Build everything outside, use only external docker containers, client extensions and rest services. Do not customize Liferay.

Maybe that’s not the intention, but in that case Liferay might want to change the tone and the way things are told to customers. I get it, client extensions and objects and data sets and so on are the shiny new toys. And I am not against that path, it’s useful stuff. But they are not the solution for every problem, especially if you do not build from scratch.

I think that the main message is to customize Liferay with the tools Liferay provides when your use case allows you to, in this way, you will have a scalable solution to upgrade and get newer features without a higher upgrade cost, but of course that is not valid for every use case.