Fiori Elements vs Freestyle SAPUI5 — The Clean Core Trade-off
“Always use Fiori Elements, it’s Clean Core safe” is one of the most repeated pieces of advice on any S/4HANA project. It is also incomplete, and I have watched incomplete advice cost a team more rework than picking freestyle honestly would have.
Fiori Elements does keep custom logic off the core, when it stays what it was built to be — a metadata-driven app that leans on annotations and defined extension points. The trap is what happens after go-live, when one small extension quietly becomes the first of several, and nobody stops to ask whether the app is still the thing it was supposed to be. Give it long enough and that Clean Core-safe app is not clean anymore, and freestyle would have been the more honest choice from day one.
This post is not the definitional comparison — that ground is already covered elsewhere on this site. This is the build decision, made through a Clean Core lens, including the failure pattern that undoes it.
🔗 Related reading
This post builds on SAPUI5 vs Fiori vs Fiori Elements — What’s the Difference? and SAP Clean Core — Strategy Behind Every S/4HANA Build Decision. If the definitions themselves are still unclear, start there. This post assumes you know what each approach is and asks a sharper question: which one actually stays clean.
What each approach actually is, in one paragraph each
Fiori Elements generates a UI from CDS annotations and OData metadata, using SAP’s standard floorplans — List Report, Object Page, Analytical List Page and others. You describe the data and its behaviour; the framework builds the screen.
Freestyle SAPUI5 is hand-built. You write the views and controllers yourself, using the same underlying framework, but without a template deciding the structure for you. Every pixel and every interaction is a decision someone made deliberately.
Both are legitimate SAPUI5 development. Neither is inherently more “Clean Core” than the other — that depends entirely on where the logic ends up living, which is the actual point of this post.
The Clean Core case for Fiori Elements
Fiori Elements earns its Clean Core reputation honestly, when used as designed. The reasoning holds up structurally, not just as marketing: an app built almost entirely from annotations has nowhere for stray custom logic to hide, because the framework never gives it a place to live inside the core in the first place.
Extension points exist as the one deliberate, upgrade-aware exit from that discipline — not a loophole, a documented one. This is covered in more depth in SAP Clean Core — Strategy Behind Every S/4HANA Build Decision.
The practical benefit shows up at upgrade time, not at build time. An app expressed almost entirely through annotations survives an S/4HANA upgrade with minimal rework, because there is very little custom code for the upgrade to break.
That is the entire economic case for defaulting to Fiori Elements — it is not about the initial build being faster, though it usually is. It is about not paying for the same app twice.
💡 Practical tip
Before adding an extension point to a Fiori Elements app, ask whether the requirement can be expressed through an annotation instead. Annotations survive upgrades cleanly. Extension points survive upgrades conditionally. Custom code inside an extension point survives upgrades the way any custom code does — with testing and risk.
Death by extension — where Fiori Elements quietly loses
Here is the failure pattern, and it has picked up an informal name among consultants because so many of us have watched it happen the same way. Nobody sets out to compromise a clean Fiori Elements app.
It happens through a series of individually reasonable requests: a field needs a different label, so a small extension goes in. A screen needs one more column than the template offers. A validation rule doesn’t fit the standard flow, so it moves into a controller extension.
Each change is defensible on its own.
The problem only becomes visible in aggregate. A year or two in, the app has enough extension points stitched together that it behaves like a freestyle build in every way that matters — except it is harder to test, harder to document, and pinned to Fiori Elements’ internal template structure rather than a clean architecture someone designed on purpose.
⚠️ Warning
A Fiori Elements app with more than a handful of extensions is not automatically Clean Core-safe just because it started that way. At some point the honest comparison is not “Fiori Elements vs freestyle” but “heavily-extended Fiori Elements vs a freestyle app that would have been easier to test, document and upgrade.” Recognising that point early is worth more than defending the original template choice.
When freestyle is the Clean Core-safe choice
It is a mistake to treat freestyle as automatically the “dirty core” option and Fiori Elements as automatically clean. Clean Core is about where logic lives, not which framework generated the screen.
A freestyle SAPUI5 app that consumes a released API, runs on SAP BTP, and contains zero custom code inside the S/4HANA core is entirely Clean Core-compliant — arguably more legibly so than a heavily-extended Fiori Elements app, because there is no ambiguity about where the custom logic lives. It is not in the core. It is in the BTP app, in full view.
This is the honest version of the decision: if the requirement genuinely does not fit a floorplan — a bespoke multi-step wizard, a non-standard layout, a highly interactive dashboard — building it freestyle from the start, off-core, is often more Clean Core-disciplined than forcing it through Fiori Elements and accumulating extensions until it resembles freestyle anyway.
✅ Best practice
Decide the build approach based on how well the requirement maps to a standard floorplan, not based on a blanket rule to “always use Fiori Elements for Clean Core.” A requirement that needs more than two or three extension points is a signal to seriously evaluate freestyle, built off-core, rather than continuing to extend.
The decision framework
| Signal | Best fit | Why |
|---|---|---|
| Requirement maps cleanly to a List Report or Object Page | Fiori Elements | Annotation-driven, minimal custom code, best upgrade safety |
| Requirement needs one or two genuine extension points | Fiori Elements, extended carefully | Still substantially annotation-driven — the Clean Core case holds |
| Requirement needs three or more extension points, or a custom controller override | Reassess — likely freestyle | The app is drifting toward freestyle complexity without freestyle’s clarity |
| Layout or interaction pattern no floorplan supports | Freestyle, built off-core where possible | Forcing it through Fiori Elements produces the same complexity with less transparency |
| Requirement will be reused as a component across several apps | Freestyle, packaged as a reusable building block | A one-off extension does not scale; a genuine component does |
The same signals map onto a simple decision flow.
Run your own requirement through that flow before you write the first line of code.
📌 Key takeaway
Fiori Elements is not Clean Core by name — it is Clean Core by how little custom code it accumulates. The moment extensions start piling up, ask honestly whether you are still building the Clean Core-safe option, or defending a template choice that has already stopped being one.
What this looks like in a real landscape
This decision sits directly underneath the frontend choice covered earlier in this series. Once a requirement has been confirmed as belonging in Fiori at all, this is the very next decision — Fiori Elements or freestyle — and it is made per app, not once for the whole landscape.
In practice, most landscapes end up with both, deliberately. Standard transactional apps — the CRUD-heavy majority — run as Fiori Elements, annotation-driven and low-maintenance. The handful of genuinely bespoke requirements run as freestyle, built off-core on BTP where possible, clearly separated from the annotation-driven majority rather than bolted onto it as extensions.
That mix, made deliberately app by app, is what keeps the Clean Core story honest across an entire landscape rather than true in theory and false in practice by the second year of any given app’s life.
At a glance — the Clean Core build decision
| Concept | One-line summary |
|---|---|
| Fiori Elements | Annotation-driven UI generation — Clean Core-safe by default, as long as extensions stay minimal |
| Freestyle SAPUI5 | Hand-built UI — not automatically “dirty core”; Clean Core-safe when it stays off-core, e.g. on BTP |
| Clean Core | About where logic lives, not which framework generated the screen |
| Death by extension | The failure pattern where incremental extensions erode a Fiori Elements app’s Clean Core advantage |
| The extension threshold | More than two or three extension points is a signal to reassess, not a reason to add a fourth |
| Reusable requirements | Better served by a freestyle building block than a one-off Fiori Elements extension |
| The real decision unit | Per app, not per landscape — most landscapes deliberately run both approaches side by side |
What to take away
“Always use Fiori Elements” is a rule for people who have not yet watched an app accumulate its fifth extension. It is a reasonable starting default, and a poor place to stop thinking.
The real Clean Core discipline is not choosing Fiori Elements once at the start of a project. It is checking, honestly, at every extension request, whether the app in front of you is still the annotation-driven, low-maintenance thing you set out to build — and being willing to call it freestyle when it no longer is.
Get that honest early, and both approaches stay exactly what they are supposed to be: Fiori Elements fast and clean for the majority, freestyle deliberate and contained for the rest.
🔗 Related reading
SAPUI5 vs Fiori vs Fiori Elements — What’s the Difference? — the definitional comparison this post builds on.
SAP Clean Core — Strategy Behind Every S/4HANA Build Decision — the strategy this entire build decision is measured against.
SAP BTP — The Platform Explained — where off-core freestyle apps typically end up living.
This post is Chapter 2 of the SAP Fiori & UX Architecture series — see “When Fiori Isn’t the Answer — Choosing the Right SAP Frontend” for the frontend decision this post assumes is already made, and “Fiori Authorization and Role Design for a Multi-System Landscape” for how role design differs between Fiori Elements and freestyle apps at scale.
Published on rakeshnarayan.com — Articles
URL: https://rakeshnarayan.com/articles/fiori-elements-vs-freestyle-sapui5-the-clean-core-trade-off/



Did you enjoy this article?
Let me know — it takes one click.
0 Comments
Leave a Comment
Looks like this one held your attention — I'd really appreciate a quick comment below.
Your comment has been submitted and will appear after review.