Six objections arrive in every warehouse engagement, usually in this order; the answers you improvise are the ones that sound like sales. Then subtract — enablement is mostly removing work, and every row below got there for a reason that made sense at the time.
Stand 29.07.2026
The kill list — take it to the sponsor with a name against each row
Stop
Why it started
Do instead
Weekly status decks
someone asked for visibility once
the two-lane declining-contribution query and the PR count, five lines in a channel — lanes, no names
Consultant on the alert rota past week 9
you are faster at 3am
team on the rota, you on standby a fortnight, then off
%run notebook chains
it worked in the prototype
workspace files and imports — %run hides the dependency graph and cannot be unit-tested
Scheduled OPTIMIZE on UC managed tables
necessary before predictive optimization existed
check whether predictive optimization is already on for this account first — if it is, the scheduled job pays a second time to compact files that were already compacted, and the two writers start losing to each other on concurrent-modification conflicts
A shared team mailbox for alerts
it felt like coverage
a named rota — a mailbox is where alerts go to be unread
Consultant as required PR approver
quality
two team reviewers; you comment without approving
Copying production data into dev
debugging
seeded fixtures in dwh_test.fixtures — a production copy in dev is a GDPR event with a ticket number
Documentation in the consultant's deck
it is what got sold
repository pages the team edits; anything only you can change dies at handover
Concede the true part first — every one of these has one
Objection
Response
You want to rewrite our working code.
No — I want to pin what it does today, then change it without changing that. Characterization test first, refactor second.
We don't have time to write tests.
You already write them: you eyeball the output in a notebook after every run. Same cost, except mine runs again next month. One assertion per bug from here; nothing retroactive.
Our data is too complex for a star schema.
Possibly. Take the three hardest questions the business asked last quarter and model only those — two hours. Usually the complexity is in the source, not the model; if it is not, we have learned something real.
Databricks does that automatically now.
Often true, and worth checking rather than arguing: predictive optimization runs OPTIMIZE, VACUUM and ANALYZE on Unity Catalog managed tables, on by default for accounts created on or after 11.11.2024. It does not decide your grain or notice that revenue is wrong.
The previous consultant said the opposite.
What problem was that solving, and does it still exist? Partitioning advice was right before liquid clustering; Databricks now recommends clustering over Z-ordering for new tables, and the two cannot be combined.
We'll do it properly later.
Name the date and price it. Retrofitting catalog-per-environment after go-live moves every table, reissues every grant, re-points every report, and has no partial rollout. 'Later' with a number attached stops being free.
The first objection decides whether the engagement works, and it is answered with code rather than reassurance. A characterization test pins current behaviour before anything is touched, so the refactor is provable instead of trusted:
Why
Improvised answers sound like sales, and a team that suspects it is being sold to stops arguing and starts complying. In a meeting compliance is indistinguishable from agreement; in the code six weeks later it is not.
Two of the six cite the platform, which is what the currency register is for. Contradicting a client who is right about Databricks — and it moves fast enough that they sometimes are — costs more credibility than any single technical point is worth.
"""Pins TODAY's behaviour of the existing customer load.
Asserts nothing about correctness -- only that the refactor changes nothing
the business can see. Delete it once the refactor is merged and reviewed.
"""
from pyspark.testing import assertDataFrameEqual
from dwh.silver.customer import clean_customer
def test_clean_customer_matches_pinned_output(spark):
source = spark.read.table("dwh_test.fixtures.sap_kna1_2026_07_01")
pinned = spark.read.table("dwh_test.fixtures.silver_customer_pinned")
actual = clean_customer(source).drop("_tech_loaded_at")
assertDataFrameEqual(
actual,
pinned.drop("_tech_loaded_at"),
checkRowOrder=False,
)
Write it with them, on their most feared module. The objection is not about code quality — it is about being blamed for breaking something that currently works. The test moves the blame onto an assertion, which is where it belongs.
Doing it
Write the six responses down before week oneYou will be asked all six, usually in this order.
Answer with a demonstration on a named date, not with an argument in the room
Concede the true part out loud, first, every time
Never a flat no: three options with their costs, per the requirements route
Check the currency register before contradicting any claim about what the platform now does by itself
Embedding it
Once you have answered an objection twice, have a team member answer it in front of their own stakeholdersIf they cannot, they were being polite rather than convinced.
Treat a repeated objection as evidence the answer was a speechWhen a team member raises one you already answered, redo it as a demonstration.
Ask which objection their sponsor will raise, and prepare them for it rather than yourself
Let them win one of these arguments against you in publicA team that has never disagreed with you is not thinking.
Defaults
Six prepared answers, each conceding something true
Schedule the demonstration rather than winning the meeting
Platform claims get checked against the currency register before they get contradicted
A characterization test before any refactor of code that currently runs in production
Gotchas
Winning the argumentThey concede in the meeting and revert in the code, and you find out at handover. The tell is agreement with no follow-up question.
Treating 'no time for tests' as a values problemIt is a schedule problem and it is usually accurate. Answer with scope — one assertion per bug — not with principle.
Dismissing the previous consultantThe team hears a verdict on their last two years, and it guarantees the next consultant dismisses you.
Flatly denying that Databricks now handles somethingHalf of these claims are true and more become true each quarter; being wrong about one costs you the other five arguments.
Answering the rewrite objection with reassurance instead of a testReassurance expires the first time a refactor breaks a report, and nothing you propose afterwards gets adopted.