Lead BI & Analytics Engineering Consultant

I make complex data useful.

I design modern analytics platforms and BI products that turn enterprise-scale data into clear, trusted decisions.

Rafael Figueiredo

Based near Frankfurt · Germany

8+years shaping
enterprise analytics
3B+records handled in
large-scale BI models
400+manager-level users
served by one solution
5languages spoken
across global teams

Experience

Work across complex enterprises.

Choose a company to expand the roles, technologies, and detailed contributions behind the work.

Deutsche BahnDeutsche LeasingSamsungWIRTGEN GROUPINNIO GroupMercedes-Benz Tech InnovationDeutsche BankRoche Diagnostics

Case studies

The whole chain, and what it took to trust it.

Public builds documented end to end — including the defects found along the way, and the limits of what the finished numbers can prove.

EU procurement: a BI product end to end

Real public tender data, taken the whole way: mismatched source systems, a Data Vault absorbing entity resolution, dimensional marts, and a governed semantic model that publishes its own coverage and integrity alongside the figures. Every measure is defined in writing before any DAX exists, and regression tests pin each one to a known filter context.

PostgreSQLdbtData VaultPower BIAirflow
Read the case study

Three numbers rendered perfectly and were wrong. Catching them is the work; the pipeline that produced them is commodity. Here is what each defect was, how it surfaced, and what the finished figures still cannot tell you.

351awards in the current sample
61.8%of award values passed the quality rules
29regression tests pinning each measure
0.3%of awards matched to a federal department

A share that could only ever be zero

Framework Share was first measured against certified value — the total that excludes awards failing the data layer's quality rules. Every framework award fails those rules, because ambiguous framework treatment is precisely what makes a value uncertifiable. The measure therefore returned 0% in every filter context, permanently, and rendered as a clean and confident zero.

Measured against the total that includes unverified values, where framework awards are actually present, it reads 45.7%. The defect was not in the DAX. It was in the choice of basis, which is the kind of mistake a syntax check cannot see.

A budget total that added income to spending

The German federal budget file contains both halves of the budget. A budget balances, so summing every row returns roughly double: €993bn against an actual 2022 Bundeshaushalt of €495.8bn — a figure that would look entirely plausible on a card.

The first digit of the Gruppierungsplan code separates them: groups 0–3 are revenue and financing, groups 4–9 are expenditure. Each half now reconciles to €495.79bn for fiscal 2022, matching the published budget. The classification began as a calculated column in the semantic model and has since moved into the warehouse, where it is source-derived and every consumer inherits it rather than re-deriving it.

A ratio that divided one slice by a different slice

Framework Share filters the same column a reader can also slice on. Without KEEPFILTERS, the measure's inner filter replaces the reader's filter instead of narrowing it. Sliced to non-framework awards, it returned 84% — framework value divided by non-framework value. Not an error and not a blank: a plausible percentage that means nothing.

Every ratio in the model now wraps its numerator filter in KEEPFILTERS, and each carries a test asserting correct behaviour when sliced by the column it filters. Most DAX defects are filter-context defects, so the suite pins measures at several contexts rather than only at the grand total.

Definitions before DAX, including the contested ones

Every measure was defined in writing before any DAX existed. If a number is defined only by the code that calculates it, the code becomes the definition, and nobody can say whether it is right — only whether it runs.

The contract also records where more than one defensible definition exists. Single-Bidder Rate is the clear case: 55 of 351 awards do not record how many companies bid. Counting only awards with a known bid count gives 19.9%; counting all awards gives 16.8%. A 3.1-point gap is not rounding, and it changes how a reader reads the finding. The first is certified, the second is published beside it, and neither ever appears without the 84.3% bid-data coverage that limits both.

The join that failed, published as a finding

The original design compared procurement volume against departmental budgets. Only 1 of 104 buyers could be matched to a federal department. The cause is structural rather than tunable: the German buyers appearing in TED are mostly municipalities, regional states, hospitals and utilities, while the federal budget covers federal ministries only. The two sets barely overlap, so better matching cannot connect them.

The comparison was removed from the report. The failed join is reported in its place — two official datasets describing related government activity that cannot be linked at this scope. Doing it properly needs regional and municipal budget data, which is a later phase.

View the repository
Warehouse, semantic model and report built · 29 model tests greenPublic repository

Brazil's largest banks: a governed BI layer on official data

Fifteen months of Brazilian central-bank COSIF filings and five macro series, taken from raw archives to a version-controlled Power BI model. Four reporting lines are mapped from top-level accounts and reconcile to the source to the cent; every measure is defined in writing before any DAX, and the report publishes its own provenance and reconciliation beside the figures.

PostgreSQLdbtDagsterPower BIdlt
Read the case study

The pipeline is commodity; trusting the numbers is the work. A balance sheet that summed itself across months, a growth measure that compiled to nothing, four lines that must never be added together — here is what each was, how it surfaced, and what the finished figures still cannot tell you.

R$13.67Ttotal assets of the top 15 banks, Mar 2026
900audited bank-month reporting-line balances
R$0.00difference reconciling marts to source accounts
214/214dbt model and test nodes green

A balance sheet that summed itself across fifteen months

The first card read R$190 trillion in total assets. A balance is a stock, not a flow: adding March's balance sheet to February's is meaningless, yet a card with no month filter sums all fifteen months and renders a confident, wrong number.

Every balance measure is now semi-additive — it returns the latest month in context, so a card shows the March snapshot of R$13.67T while the monthly trend line is untouched. The defect was not in the arithmetic; it was in treating a stock like a flow.

A growth measure that compiled to nothing

Month-over-month growth first used DATEADD. The date table is monthly-grain — fifteen rows, one per reporting month — and DATEADD needs a daily-contiguous calendar, so it failed while every other visual rendered. Rewritten with EDATE and an explicit filter over the date table, it works on a monthly grain.

A stranger failure hid underneath: the same measure silently compiled to an error stub because a variable was named Current — a token this DAX parser reserves and rejects without a visible error. Renamed to CurVal, it compiles. Both are the kind of defect a syntax check cannot see; catching them meant querying the live model, not trusting that it loaded.

Four lines that must never be added together

Total assets, credit portfolio, deposits and equity span different sides of the balance sheet: two are assets, one is a liability, one is equity. Summed, they are nonsense. So the model never totals them, and every ratio divides by total assets — the only certified denominator.

A generic 'mapping coverage' measure was dropped for the same reason: COSIF accounts are hierarchical, so a parent already contains its children, and there is no single meaningful denominator across mixed sides. Coverage, where it means anything, is expressed per side — credit as a share of assets already is that.

Definitions before DAX, and a contract that says what is not certified

Every measure was defined in writing before any DAX existed, each with a status. Total assets is certified against the reproduced source ranking; credit, deposits and equity are governed drafts, because the account mapping is defensible but not yet formally approved. If a number is defined only by its code, the code becomes the definition and nobody can say whether it is right.

The data layer deliberately computes none of the business ratios. It delivers the certified marts and guarantees their shape; the ratios and their contested denominators live in a measure contract, where they can be seen and argued with rather than buried in a measure.

Trust as a page, reconciliation stated honestly

The report carries a Trust page: the latest source period, the active file checksum, retrieval dates stated separately from reporting dates, the seven-account-to-four-line mapping, and a plain scope statement. It reads only the certified marts — the BI layer never touches raw, staging or core tables.

Reconciliation is stated as a certification-time fact — reporting-line balances reproduce the mapped source-account sums to the cent — rather than a live figure, because the warehouse does not re-reconcile on refresh. Claiming otherwise would be a more confident number that means less.

View the repository
Data layer certified · Power BI model and three-page report built and verified livePublic repository

Currently building

Tools built from the problems worth solving once.

Side projects that came out of consulting work, built to remove the manual step the next time it appears.

Metadata-driven Medallion for Fabric

A config-over-code ingestion framework. Metadata control tables drive the Bronze, Silver, and bridge layers feeding a Direct Lake semantic model, so onboarding a table means inserting metadata rows rather than writing code. Reconciliation fails loudly on mismatch, and the whole framework installs from the browser.

Microsoft FabricPySparkPythonMedallion
Deployed and runningPrivate repository

Fabric semantic-model toolkit

Notebook drivers for the model operations that otherwise get clicked through a UI: incremental-refresh lifecycle, read-only diagnostics down to per-column VertiPaq footprint, TOM metadata surgery, and cross-workspace model cloning with report rebinding.

Microsoft FabricTOMXMLAPython
In use · v0.6.0Private repository

Power BI design ecosystem

Three reusable layers so Power BI design stops re-solving the same problems on every project: a brand-aware theme system, a typed registry of report components, and a builder that assembles reports from a spec under a theme.

Power BIPBIRThemingPython
Theme layer built · components and builder in progressPrivate repository

What I bring

From raw data to confident action.

I work across the full analytics journey—with particular depth where engineering, BI design, and adoption meet.

BI products

Power BI and Tableau experiences built around the decisions people actually need to make.

Power BI · Tableau · DAX · UX

Analytics engineering

Reusable semantic models, tested transformations, and pipelines that stay understandable as they scale.

SQL · Python · dbt · PySpark

Modern data platforms

Pragmatic architectures spanning ingestion, Lakehouse layers, modelling, and governed consumption.

Fabric · Azure · Databricks · AWS

Technical leadership

A collaborative lead for migrations, standards, mentoring, stakeholder alignment, and team enablement.

Strategy · Training · CI/CD · SAFe
The best analytics product isn't the busiest dashboard. It's the one people trust enough to act on.

I combine hands-on engineering with a consultant's eye for the wider system: the business question, the data model, the interface, and the people who will own it next.

01

Frame the decision

Start with the business question, the audience, and what a better decision should look like.

02

Engineer the foundation

Build the models, pipelines, and delivery practices that make trustworthy analytics repeatable.

03

Leave the team stronger

Share patterns, coach collaborators, and make the finished system easier to own and improve.

Available for selected hybrid and remote projects

Have a complex BI challenge?

Let's turn it into a clear next step.

Start a conversation
Aschaffenburg · Frankfurt areaEnglish · German · Portuguese