Building the Platform
A Databricks exercise in shared functions and Delta time travel, turning a hand-run notebook into a platform the next engineer can rerun without asking how.
SantéFlux is a Paris health service that turns hospital and pharmacy extracts into regional analytics for care providers across France. Every report was a notebook someone ran by hand, with the same three derivation rules pasted into each one, already drifting apart. The board wanted dependable regional figures on demand. The brief was a Databricks platform: shared logic, a table that remembers its own history, and a job that rebuilds it unattended.
The problem
Two files land in the workspace every day: patients, one row per person, and events, one row per clinical episode. The age band, cost flag and risk score every report depends on were written inline in whichever notebook needed them, and two copies had already disagreed on the same patient’s score. The reporting table itself was a full overwrite each morning, so a figure that looked wrong on Thursday couldn’t be compared with Wednesday, explained, or rolled back, the evidence was simply gone. And every one of those reports existed only because an engineer sat down and pressed the cells in order. SantéFlux’s data lead put it directly: “If a number looks wrong on Thursday, I need to see what changed and roll it back. Right now I cannot even tell you what yesterday’s table held.”
The approach
Four moves, each closing one of those three failures, built in a specific order because the order is the point. Reuse first: the derived fields become named functions in a notebook of their own, so a corrected rule lands everywhere at once. History second: the joined, enriched result gets written as Delta, not overwritten, so every write is a version you can read or roll back. Automation last: the whole thing takes a region parameter and runs on a schedule, so the report exists whether or not anyone is at the keyboard that morning.
View full size (opens in a new tab)Set up the catalog, then read the data
Everything lives under one catalog, with its own schema and volume, so the platform has a governed home before a single row is read.
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)Shared functions: write the rule once
Three fields, each a plain function that takes a column and returns a column, so the logic exists in exactly one place rather than copied into whichever notebook needs it.
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)Keep the join from producing two columns with one name
Both patients and events carry a region column, patients recording where someone lives, events recording where the episode happened. A plain join on patient_id leaves both in the result, ambiguous to any downstream query that references region, and the two values won't always agree for a patient treated outside their home area.
The join keeps events.region and explicitly drops patients.region before the two tables ever collide:
joined_df = patients.join(events,"patient_id","left").drop(patients.region)That’s a business decision as much as a syntax fix. SantéFlux’s board wants regional cost and trend figures, and the region that determines which provider incurred the cost is where the episode happened, not necessarily where the patient’s address is registered. Dropping the patient’s copy keeps the surviving region column unambiguous for every function and every report built on top of joined_df, and it keeps that column meaning the same thing every time someone reads it.
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)Enrich, then look at it three different ways
The three shared functions get applied to the joined data in one chained expression, then the result gets inspected with print, show and display, a deliberate comparison of what each actually returns.
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)A quick regional count, three ways to have written it
Before writing the table, the notebook checks how many events landed in each region, a small aside that’s really about knowing when it’s safe to pull data back to the driver.
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)Version the table, prove the rollback
The enriched result is written as a managed Delta table, and every subsequent write becomes a version rather than a replacement.
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)To prove the rollback actually works, the next cell deliberately breaks the table: every risk score in the entire dataset gets set to zero, no WHERE clause, the exact kind of Thursday-morning mistake the brief opened with.
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)
View full size (opens in a new tab)Schedule the job
The last step turns the region widget into a job parameter and wires the main notebook to a Databricks Job on a daily trigger, so the platform runs whether or not an engineer is watching.
View full size (opens in a new tab)The schedule itself is worth a second look: it’s set to 09:00 in the workspace’s own timezone, Asia/Calcutta, rather than Europe/Paris. Harmless for a bootcamp job, but exactly the kind of detail that needs fixing before this platform actually reports on the morning a Paris care provider is expecting, not the morning IST happens to deliver it.
What this proves
Reuse, then history, then automation, in that order, because reversing it ships the fragility it was meant to remove: functions shared before the join means a corrected rule lands everywhere at once, the table versioned before it’s trusted means a Thursday mistake is a RESTORE away from Wednesday, and the run handed to a schedule last means neither of the first two matter if someone still has to remember to press the cells.