Services
From raw records to a number people can defend.
Three kinds of work, usually in the same engagement: the lakehouse platform, the Power BI semantic model on top of it, and the business logic in between that decides which number is right.
Reporting calendar check: in one week, at a fixed price, we measure how far your weekly and monthly reports disagree and show how one calendar fixes it for every report. See the calendar case study
04 Transformation
Quality is a stage in the pipeline, not a hope at the end of it.
A deduplication key, a returns policy, which month a Saturday belongs to: every rule that changes a number lives in one place, is versioned, and is tested before it reaches a report.
- Failed records are quarantined and counted, never silently dropped.
- Every gold table declares its grain.
- Lineage runs from report measure back to source column.
Tools follow the client platform. Not every project uses every tool shown.
- SourceOperational systems, files, events, APIs.
- IngestIncremental and idempotent. Late data is expected, not exceptional.Fabric · Databricks · PySpark
- RawKept exactly as delivered, with load metadata. Replayable.Delta Lake · OneLake
- Transform
- QualityType, null, range and referential checks. Failures quarantined.
- DeduplicationBusiness keys, not row hashes alone. Deterministic survivorship.
- Business rulesReturns, voids, promotions and calendar assignment, written once.
- HistorySlowly changing dimensions where the past must stay reproducible.
- CuratedConformed dimensions and facts at a declared grain.dbt · SQL · Unity Catalog
- SemanticRelationships, measures and the date dimension every report shares.Power BI semantic models
- BIReports that answer the next question, not only the first.Power BI
05 Semantic model
Trustworthy BI is a modelling decision, not a charting one.
One fact table at a declared grain. Dimensions that keep their history. A date table that every report reads its periods from. Charts come last.
Fact · related to all four dimensions
Sales
- Grain
- One row per receipt line
- Carries
- Net amount, units and discount, plus a key to every dimension
- Why it matters
- Measures are defined once here. Every report reuses them instead of re-deriving them.
Select any table to see its role in the model.
06 Analytics
A report should answer the next question too.
“Revenue is up” starts a conversation. A model where every driver is a dimension finishes it, in the same report, without an export to a spreadsheet.
Business question
Why did monthly revenue move?
Net sales, P02 → P03: +0.41M (8.7%)
Net sales bridge, P02 to P03
IllustrativeAxis starts at 4.40M.
Trading days +0.21M
P02 lost a trading day to a public-holiday closure; P03 traded every day. The calendar explains this, not the customers.
Model fields Date[IsTradingDay] · Date[HolidayName]
| Step | Value |
|---|---|
| P02 | 4.70M |
| Trading days | +0.21M |
| Promotion | +0.14M |
| Customer mix | −0.06M |
| Product mix | +0.12M |
| P03 | 5.11M |
07 Stack
Tools, grouped by the job they do.
Chosen to fit the client platform. The modelling discipline stays the same on every one.
Platform
- Azure
- Azure Databricks
- Databricks Partner
- Microsoft Fabric
- OneLake
- Snowflake
Engineering
- Python
- PySpark
- SQL
- dbt
Modelling
- Delta Lake
- Unity Catalog
- Data Vault 2.0
- Kimball
Analytics
- Power BI
- Semantic models
Infrastructure
- Terraform
- CI/CD