← All posts

Why OutSystems Projects Fail at the Data Layer

Most OutSystems projects don't fail because of OutSystems. They fail because of data layer decisions made in the first few weeks that nobody questions until production. Here's what we actually see.

 

Most OutSystems projects don’t fail because of OutSystems.

They fail because of decisions made in the first few weeks that nobody questions until the system is in production and something is wrong. By then the cost of fixing it is ten times what it would have cost to get it right.

In our experience building on O11 across enterprise environments — including New Zealand’s largest OutSystems platform, used by 10,000+ people daily — the same patterns come up. They’re not exotic. They’re not edge cases. They’re the same mistakes, repeated, because they’re invisible until they aren’t.

Here’s what we actually see.


1. Aggregates doing work they shouldn’t be doing

OutSystems makes it easy to build aggregates. Drag a few entities, add some filters, done. The problem is that ease of use creates a false ceiling — developers reach for aggregates by default even when the query complexity has outgrown what aggregates handle well.

The symptom is a reporting screen that takes eight seconds to load. Or a dashboard that’s correct for one restaurant but wrong for ten. Or a scheduled job that runs fine in development and times out in production.

The root cause is almost always an aggregate that’s doing joins, filters, and calculations across a dataset it was never designed to handle at that scale.

The fix isn’t always dropping into advanced SQL. Sometimes it’s restructuring the data model. Sometimes it’s moving calculation logic server-side. But you can’t fix what you haven’t diagnosed — and most teams don’t diagnose it until a stakeholder complains.


2. Multi-tenancy bolted on after the fact

This one is expensive.

Building a system for one tenant and then expanding it to many is one of the most common sources of rework we see in enterprise O11 projects. The original architecture didn’t account for tenant scoping — queries return data across all sites, aggregates don’t filter correctly, scheduled jobs run against the wrong dataset.

The right time to design multi-tenancy is before you write the first query. Every entity, every aggregate, every service action needs a clear answer to the question: how does this scope to a specific tenant?

When that question gets deferred, the answer becomes a refactor. And refactors in production systems with real users are exactly as painful as they sound.


3. Calculated fields living in the wrong place

OutSystems gives you a lot of places to put logic — aggregates, preparation, client actions, server actions, timers. The data layer failure mode here is business logic that should live server-side ending up in the UI layer, or calculations that should happen once at write time happening repeatedly at read time.

The clearest example: a KPI that gets calculated every time a screen loads, pulling raw transaction data, aggregating it on the fly, applying business rules inline. It works fine with ten records. It doesn’t work at all with ten thousand.

The question to ask is always: when should this calculation happen, and where should the result live? If the answer isn’t clear before you build it, it will become clear later — at the worst possible time.


4. Scheduled jobs that aren’t safe to rerun

Production systems fail. Servers restart, timeouts happen, jobs get interrupted mid-execution. This is not exceptional — it’s normal.

The failure mode is a scheduled job that wasn’t designed with this in mind. It runs halfway, writes partial data, fails, and now the system is in an inconsistent state. The next run either duplicates the partial data or errors out entirely.

Idempotency — designing jobs so they can run multiple times without corrupting the result — isn’t an advanced concept. It’s a basic requirement for any scheduled process in a production system. But it requires thinking about failure before it happens, which is the kind of thinking that gets skipped when the pressure is on to ship.

We build every pipeline idempotent from day one. Not because we expect failure. Because failure is guaranteed eventually and the system needs to recover cleanly when it happens.


5. The data model that made sense at the start

Entity design decisions made in week one have a way of hardening into permanent constraints. A field that was added quickly becomes load-bearing. A relationship that seemed right for the initial scope becomes wrong for the scale the system eventually reaches.

This isn’t unique to OutSystems — it’s true of any system. But O11’s visual development model can make it feel faster to add to a model than to question it, which means bad early decisions compound faster than they would in a traditional codebase.

The discipline is treating the data model as a first-class design decision, not a side effect of building screens. The entities are the system. Everything else is presentation.


What this actually looks like in practice

On the platform we work on — NZ’s largest O11 environment — every one of these patterns was either already present or had to be actively designed against.

The stock consumption pipeline needed idempotency because period-close operations in a live restaurant estate cannot produce incorrect variance data under any failure condition. The multi-tenant architecture needed to be right from the start because the system runs across dozens of restaurants and every query scopes to a specific site. The reporting layer needed server-side calculation because KPI dashboards used by operations managers need to be fast and correct at 7am before a shift starts.

None of these were afterthoughts. They were constraints we understood before we wrote the first line.


The uncomfortable truth

Most of these failures aren’t technical failures. They’re process failures. The data layer goes wrong because the architecture conversation didn’t happen early enough, or didn’t involve someone who’d seen these patterns before, or got skipped entirely in the rush to start building.

OutSystems is a capable platform. It handles enterprise-scale systems well when the foundations are right. The problem is that its ease of use can create the illusion that foundations don’t matter — that you can move fast and fix it later.

You can’t. Not at enterprise scale. Not in production. Not when real people depend on it every day.


If you’re building on OutSystems O11 and want to talk through where your architecture stands — before the symptoms show up in production — we’re happy to have that conversation.

Book a discovery call →