Technology - SAP

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.

Five-stage progression diagram on white background showing a Fiori Elements app gradually accumulating extensions over time until it behaves like an unplanned freestyle build

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

SignalBest fitWhy
Requirement maps cleanly to a List Report or Object PageFiori ElementsAnnotation-driven, minimal custom code, best upgrade safety
Requirement needs one or two genuine extension pointsFiori Elements, extended carefullyStill substantially annotation-driven — the Clean Core case holds
Requirement needs three or more extension points, or a custom controller overrideReassess — likely freestyleThe app is drifting toward freestyle complexity without freestyle’s clarity
Layout or interaction pattern no floorplan supportsFreestyle, built off-core where possibleForcing it through Fiori Elements produces the same complexity with less transparency
Requirement will be reused as a component across several appsFreestyle, packaged as a reusable building blockA one-off extension does not scale; a genuine component does

The same signals map onto a simple decision flow.

Decision flow diagram on white background showing how floorplan fit and extension-point count route a requirement to Fiori Elements or a reassessment toward freestyle SAPUI5

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.

Landscape diagram on white background showing a majority grid of Fiori Elements apps alongside two separate freestyle SAPUI5 apps built off-core on SAP BTP within one S/4HANA landscape

At a glance — the Clean Core build decision

ConceptOne-line summary
Fiori ElementsAnnotation-driven UI generation — Clean Core-safe by default, as long as extensions stay minimal
Freestyle SAPUI5Hand-built UI — not automatically “dirty core”; Clean Core-safe when it stays off-core, e.g. on BTP
Clean CoreAbout where logic lives, not which framework generated the screen
Death by extensionThe failure pattern where incremental extensions erode a Fiori Elements app’s Clean Core advantage
The extension thresholdMore than two or three extension points is a signal to reassess, not a reason to add a fourth
Reusable requirementsBetter served by a freestyle building block than a one-off Fiori Elements extension
The real decision unitPer 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/