← All posts

FlowFields, FlowFilters and CalcFormulas in Business Central — a practical guide

23 March 2026 9 min read Mike Tawn
Business Central FlowFields FlowFilters CalcFormulas AL Development BC Performance BC Schema

If you have spent any time inside Business Central — as a developer, a consultant, or even an advanced end user trying to understand where a number comes from — you have encountered FlowFields. They are one of the most powerful features in the platform. They are also one of the most misunderstood.

This post explains what FlowFields, FlowFilters, and CalcFormulas actually are, how they work under the hood, why they matter for performance, and how to explore them across your BC schema.

What is a FlowField?

A FlowField is a field that does not store data. Its value is calculated on the fly from data in another table (or sometimes the same table) every time it is read. Think of it as a live aggregate — a sum, a count, an average, a lookup — that is always current because it runs at the moment you ask for it.

The classic example is the Balance field on the Customer table. It does not contain a stored number. Instead, it is defined as a FlowField with a CalcFormula that sums the Amount field on the Customer Ledger Entry table, filtered to open entries for that customer. Every time you open a customer card, BC runs that calculation and shows you the live balance.

Other common examples:

If you have ever wondered why certain fields seem to always be up to date without anyone posting anything, FlowFields are the answer.

How a CalcFormula works

Every FlowField has a CalcFormula that defines its calculation. The formula specifies four things:

  1. The method — Sum, Count, Average, Min, Max, Lookup, or Exist
  2. The source table — which table to read from
  3. The source field — which field to aggregate (for Sum, Average, Min, Max) or retrieve (for Lookup)
  4. The filters — which records in the source table to include

In AL code, a CalcFormula looks like this:

field(59; Balance; Decimal)
{
    CalcFormula = sum("Cust. Ledger Entry".Amount
                      where("Customer No." = field("No."),
                            "Global Dimension 1 Code" = field("Global Dimension 1 Filter"),
                            "Global Dimension 2 Code" = field("Global Dimension 2 Filter"),
                            "Currency Code" = field("Currency Filter")));
    FieldClass = FlowField;
}

Reading this: the Balance field sums the Amount column from the Cust. Ledger Entry table, filtered where the Customer No. matches the current record and optionally filtered by dimension and currency FlowFilters.

The important thing to notice is the field(...) references in the filters. These are not hardcoded values — they refer to other fields on the same record. Some of those fields are ordinary fields (like "No."), but some are FlowFilters.

What is a FlowFilter?

A FlowFilter is a special type of field that exists solely to modify FlowField calculations. Like FlowFields, FlowFilters do not store data. They are filters that you can set at runtime to change what a FlowField returns.

On the Customer table, the Date Filter is a FlowFilter. When you set a date range on it, every FlowField that references it in its CalcFormula recalculates using only entries within that date range. Set it to the current fiscal year and suddenly the Balance field shows only this year's balance. Clear it and you get the all-time balance.

Other common FlowFilters:

FlowFilters are what make the BC statistics pages work. When you open Customer Statistics, the page sets different date ranges on the Date Filter for each column — current month, current year, all time — and the same FlowFields return different values for each.

When do FlowFields actually calculate?

This is where performance enters the picture. A FlowField does not calculate automatically just because it exists on a record. It calculates when one of two things happens:

  1. You call CalcFields in AL code — this explicitly triggers the calculation
  2. The field appears on a page — BC automatically calls CalcFields for FlowFields that are bound to visible page controls

If you retrieve a record using Get or FindFirst and never call CalcFields, the FlowField value is zero (or blank). This is a common source of bugs for developers who expect FlowFields to always have values.

In AL:

Customer.Get(CustomerNo);
// Customer.Balance is 0 here — not yet calculated

Customer.CalcFields(Balance);
// Now Customer.Balance has the real value

When you query data through an API or external tool, FlowFields behave differently depending on how you request them. Standard BC API pages typically call CalcFields for you. OData queries on raw tables may not. This is why FlowField columns sometimes appear blank in external tools — the calculation was never triggered.

The performance cost

Every FlowField calculation is a SQL query. When BC calculates the Balance field on a Customer record, it runs something like SELECT SUM(Amount) FROM [Cust_ Ledger Entry] WHERE [Customer No_] = @custNo. That is one query, for one field, on one record.

Now imagine loading a list page with 50 customers, each showing Balance, Balance Due, and Outstanding Orders. That is 50 × 3 = 150 SQL queries just to render the list. If the ledger entry table has millions of rows and the indexes are not ideal, you will feel it.

This is why:

In XPT Data Explorer, FlowFields are flagged with a yellow ⚡ FLOW badge in the field list. When you select FlowFields for a query, the performance gate shows you how many are included and warns you about the per-record cost. This makes it easy to see which fields are FlowFields before you run a query, and to make an informed decision about whether to include them.

How to explore FlowFields in your schema

Understanding which fields on a table are FlowFields — and what they calculate from — is one of the most common tasks for anyone working with BC data. Here are practical ways to explore them:

In XPT Data Explorer

Open any table in the schema browser and look at the Class column. Fields marked FlowField have their value calculated, not stored. Fields marked FlowFilter are the runtime filters that modify those calculations. Normal fields show Normal.

The field cross-reference feature ("Where Used") is particularly useful here. Expand a FlowField and you can see which tables and fields feed into it. This is how you trace where a number comes from without reading AL source code.

The static schema reference is also useful for quick lookups. Every table page lists all fields with their class, so you can bookmark the tables you work with most and check field types at a glance. Try Customer #18 or Item #27 to see FlowFields on the most common master data tables.

In AL code

If you have access to the AL source, search for FieldClass = FlowField to find all FlowField declarations. The CalcFormula immediately above it tells you what it calculates. In VS Code with the AL Language extension, you can Ctrl+click through to the source table.

In the BC web client

On any page, you can use the page inspector (Ctrl+Alt+F1) to see field details. The Expression property shows the CalcFormula for FlowFields. This works without developer access — anyone with a BC login can use it.

Common patterns to watch for

Once you know what FlowFields are, you start noticing patterns across the BC schema:

Master tables aggregate from ledger entries. Customer, Vendor, Item, Bank Account, Fixed Asset — all of these have FlowFields that sum, count, or look up values from their corresponding ledger entry tables. The master record is the anchor; the ledger entries are the transactions.

Document tables aggregate from lines. Sales Header has FlowFields that sum amounts from Sales Line. Purchase Header does the same from Purchase Line. The header knows its totals because FlowFields calculate them from the lines, not because someone stored them.

Setup tables use Exist FlowFields. Some FlowFields do not sum or count — they just check whether a related record exists. This is common in setup and configuration tables where the presence of a record in another table determines a flag or status.

Dimension filters appear everywhere. Global Dimension 1 Filter and Global Dimension 2 Filter are FlowFilters on almost every table that has financial FlowFields. They thread through from the master data tables to the ledger entry tables, allowing any FlowField to be sliced by dimension without storing dimension-specific totals.

Why this matters for data projects

If you are working on a data migration, an integration, or a report, understanding FlowFields changes how you approach the work:


FlowFields, FlowFilters, and CalcFormulas are foundational to how Business Central works. Once you understand them, the BC data model stops feeling like a black box. Numbers have traceable origins, performance issues have clear causes, and the schema starts making sense as a coherent design rather than a random collection of tables.

If you want to explore FlowFields across your own BC environment, XPT Data Explorer is free to use with the Cronus demo data — no signup needed. Every field shows its class, type, and relations. It is the fastest way to understand what is going on inside any BC table.


Explore Business Central data in your browser

Open Data Explorer →