Data Governance, Contracts, and Classification Questions
Governing data at scale: data contracts between producers and consumers, schema evolution/compatibility, data classification and sensitivity tagging, access control, and lineage/cataloging. Covers policy, ownership, and compliance-driven controls over data. The governance layer over the technical stack.
Design a lightweight data governance policy for a mid-size company: what would it cover (data ownership, schema-change approvals, PII tagging, lifecycle and retention), and how would you operationalize it so it's enforced by tooling rather than relying on people remembering to follow a wiki page?
Sample Answer
Direct answer
A lightweight governance policy for a mid-size company should cover four areas: data ownership, schema-change approvals, personally identifiable information (PII) tagging, and lifecycle and retention. To make it stick, encode each one as a check that tooling enforces automatically (a pipeline blocked from deploying, a table blocked from being created) rather than a rule written on a wiki page that depends on people remembering to follow it.
Structured elaboration
Data ownership. Every dataset has a named owner, recorded in the catalog at creation time, not added later if someone asks. Operationalize it by making the owner field a required, non-empty field in the dataset-creation tooling (a table creation script or Terraform module that will not run without it), rather than a policy statement that ownership "should" be recorded.
Schema-change approvals. A breaking schema change (removing a field, tightening nullability, changing a type) requires review before it ships, while an additive, backward-compatible change (adding a new nullable field) can go through automatically. Operationalize it with a CI check that classifies the change (breaking versus additive) by diffing the new schema against the previous one, and only routes breaking changes to a required human approval step, so the policy is enforced by the pipeline, not by hoping the engineer remembers to ask.
PII tagging. Any field containing personally identifiable information (PII), directly identifying (name, email) or indirectly identifying in combination with other fields, is tagged as such in the catalog, and that tag drives masking or access restriction automatically. Operationalize it with an automated PII-detection scan (pattern matching on column names and sampled values) that runs on every new table and flags likely PII for a human to confirm, rather than relying on the table's creator to remember to self-report it.
Lifecycle and retention. Every dataset has a stated retention period, driven by its sensitivity classification and any PII it contains, after which it is automatically archived or deleted. Operationalize it with a scheduled job that reads the retention field from the catalog and acts on it, rather than a policy that retention "should" be respected with no automated enforcement.
Worked example
A new table, signup_events, is created. The creation tooling requires an owner field (the growth team lead is entered) before the table can be provisioned at all. The automated PII scan flags the email column as likely PII based on its name and sampled values; a human confirms it, and the catalog tags the column, which triggers an automatic column-level masking policy for any role without an explicit PII-access grant. Because the table contains PII, its default retention (driven by the sensitivity/PII policy) is set to 18 months rather than the standard non-PII default of 5 years, and a scheduled job will archive rows past that age without anyone needing to remember to run a manual cleanup.
Trade-offs & pitfalls
Automated PII detection based on column names and sampled values produces both false positives (a column named user_ref that is actually an internal, non-identifying ID) and false negatives (a free-text notes field that occasionally contains a customer's name typed in by a support agent, which pattern matching on the column as a whole will likely miss), so it needs a human-review step, not full automation, and the review step is exactly where deadline pressure tends to erode the policy if it becomes a bottleneck. Schema-change classification (breaking versus additive) can also misjudge a case where an additive-looking change actually breaks a downstream consumer's business logic even though it does not break the schema mechanically, tooling catches structural breakage, not semantic breakage. And a retention policy enforced by a scheduled deletion job is unforgiving of a mistake, if a dataset is mis-tagged as containing less-sensitive data than it does, the shorter automated deletion the mis-tag implies can be the safer failure mode, but a longer-than-intended retention on genuinely sensitive data is the more dangerous one, so retention defaults should err conservative when tagging confidence is low.
A partner offers you a third-party dataset for use in a production model or analytics pipeline. What contractual, security, and technical steps would you require before it goes live: what data-sharing or legal clauses would you want, how would you validate its schema and quality against your expectations, and how would you shadow-test the integration before fully trusting it?
Sample Answer
Before a third-party dataset goes live in production, treat it like any other producer relationship plus an extra layer of due diligence you cannot do for an internal team: pin down the legal terms of use and liability, validate the data's actual schema and quality against what was promised rather than trusting the sales materials, and run it in shadow, consuming and comparing without acting on it, before it is allowed to influence a real decision.
Contractual and legal steps
- A data-sharing or licensing agreement specifying exactly what you are allowed to do with the data, train a model on it, redistribute derived outputs, retain it after the contract ends, and what you are not.
- Liability and indemnification terms: what happens if the data turns out to be inaccurate, improperly sourced, or the partner did not have the rights to share it in the first place.
- Data provenance and compliance representations: does the partner warrant the data was collected lawfully, including consent where required, for the jurisdictions it covers; this matters even more if any of it touches personal data, since your own liability for how you use it generally does not disappear because a partner supplied it.
- A service-level agreement on delivery: how often it is refreshed, what happens on a missed delivery, and a defined support or escalation contact, the same shape as an internal data contract's freshness and ownership fields.
Security steps
- Review how the data is transmitted and stored, encrypted in transit and at rest, access scoped to only the people and systems that need it, before it lands anywhere near production infrastructure.
- Treat an external dataset as untrusted input until validated: it should not have broader access or fewer controls than data generated internally, and ideally it lands in a staging or quarantine area first, not directly into the production pipeline's live tables.
Technical validation: schema and quality
- Validate the actual schema against what the partner documented: field names, types, nullability, and cardinality, the same schema-diff discipline used for an internal producer's contract.
- Check data quality empirically: null rates, duplicate rates, value-range sanity, and freshness against the promised service-level agreement, on a real sample, not the vendor's summary statistics alone.
- Confirm join keys and semantics line up with your own data; a partner's
customer_idmeaning something different from yours is a classic silent-corruption source.
Shadow-testing before fully trusting it
Before the new dataset drives a real decision, a served model prediction or a published report, run it in parallel with the existing source of truth, if one exists, or in an inert mode where its output is logged and compared but not acted on. For a model feature, this means computing predictions with and without the new data and comparing them, or serving the new feature to a held-out slice while measuring downstream metrics before it becomes part of the production feature set. This surfaces integration bugs and quality issues that only show up under real production volume and skew, which a one-time validation pass on a sample will not catch.
Worked example
A partner offers a firmographic dataset, company size, industry, and revenue band, to enrich a lead-scoring model. Legal review confirms the contract permits using the data to train and serve the model but not to resell enriched records to a third party, and requires deleting the partner's data within thirty days of contract termination. Security confirms delivery is via an encrypted storage bucket with access scoped to the ingestion pipeline's service role only, landing in a quarantine schema first. Technical validation finds the partner's documented schema is accurate but the revenue_band field has a noticeably higher null rate on the sample pull than the partner's documentation implied, which gets raised back to the partner as a data-quality issue before proceeding, and the model team decides to treat a null revenue_band as a separate "unknown" bucket in the feature rather than assuming a default. The feature is then shadow-served for two weeks: predictions are computed with the new firmographic feature included, but the production model still serves without it, and the shadow predictions are logged and compared against actual lead-conversion outcomes before the team promotes the feature into the live model.
Trade-offs and pitfalls
Skipping the shadow-test step to hit a launch date is the single most common way a third-party dataset causes a production incident, because vendor-reported quality and observed quality routinely disagree, and the disagreement usually only shows up at real volume. On the legal side, the common mistake is treating a partner's compliance representations as sufficient due diligence; your own liability for how you use personal data generally does not transfer away just because a contract says the partner warranted it.
Design a schema registry and CI enforcement setup for a streaming or event-driven platform: how do you register schemas, run compatibility checks before a producer's change ships, and alert on or block a breaking change? Discuss how this differs for a Kafka/Avro event stream versus a batch warehouse table, and what a schema registry buys you beyond just documentation.
Sample Answer
A schema registry is a centralized, versioned store of the schemas producers and consumers agree on, keyed by subject (typically the topic name), that a serializer or deserializer consults at write and read time, and that CI (continuous integration) can query to check whether a proposed schema change is compatible with what is already registered. The design has three parts: a registration and versioning API, a CI-time compatibility gate, and a runtime alerting or blocking mechanism. The same idea applies to a batch warehouse table, but the enforcement points differ because there is no per-message serializer to intercept.
Core components
- Registry service: stores schemas per subject, with a version history and a compatibility mode (backward, forward, or full) configured per subject.
- Producer-side serializer: before writing, looks up or registers the schema for the topic; the registry rejects registration if it violates the subject's compatibility mode.
- Consumer-side deserializer: looks up the writer's schema, identified by a small ID embedded in each message, and resolves it against the reader's own schema.
Registering schemas
On first deploy, the producer registers its Avro (a data serialization format commonly used for streaming events), Protobuf (Google's binary serialization format), or JSON Schema definition against a subject name, commonly <topic>-value. Every subsequent message carries that schema ID rather than the whole schema, keeping the wire format compact; the consumer fetches the corresponding schema from the registry by ID and caches it locally.
CI enforcement before a producer's change ships
The registration step is the gate: a CI job on the producer's pull request (PR) calls the registry's compatibility-check endpoint with the new schema before merge, using the subject's configured mode. An incompatible change fails the CI job, so it never reaches deploy.
Alerting on and blocking breaking changes
Two layers matter. First, the registry itself blocks a genuinely incompatible schema from being registered at all when enforcement is strict, so a bad change cannot land even if someone tries to bypass CI locally. Second, for cases a schema-level check does not fully cover (someone bypasses the registered serializer, or a batch job silently changes a table without going through a registry), a monitoring layer should watch for shape drift at runtime, comparing incoming data's actual shape against the last known-good schema, and alert or quarantine to a dead-letter path rather than let malformed records flow downstream silently.
Kafka/Avro streaming versus a batch warehouse table
For a Kafka (a distributed event-streaming platform) topic using Avro, enforcement is naturally per-message and synchronous: the serializer-registry interaction happens on every write, so a breaking change is caught within the first bad message, before it is even durably written. For a batch warehouse table, there is no per-row serializer in the loop, so the equivalent controls have to live earlier and later in the pipeline: earlier as a CI check against the table's DDL or dbt (a SQL-based data transformation tool) model definition before the pipeline deploys, and later as a data-quality check on the loaded output (row counts, null rates, a schema diff against the prior run) that alerts before downstream consumers query a broken table. The batch case also has to deal with older and newer partitions or files coexisting under different schema versions, which a streaming registry mostly avoids because each message is evaluated individually against the current subject schema.
What a schema registry buys beyond documentation
A written schema document can go stale the moment someone changes the producer's code. A registry makes the schema the mechanism the pipeline actually runs on: the producer cannot write a message the registry considers incompatible when enforcement is on, so the schema and the guarantee are the same artifact, not a document describing a guarantee nobody checks. It also provides a machine-readable version history, a stable schema ID on the wire (cheaper than repeating field names on every message), and a query surface other tools, like data catalogs and lineage systems, can read from instead of re-deriving structure by sampling data.
flowchart LR
Dev[Developer PR: new schema] --> CI[CI: compatibility check]
CI -->|compatible| Registry[(Schema Registry)]
CI -->|incompatible| Block[Build fails, PR blocked]
Registry --> Producer[Producer serializer]
Producer -->|schema ID + payload| Topic[(Kafka topic)]
Topic --> Consumer[Consumer deserializer]
Consumer --> Registry
Worked example
A payments.charge_created Avro schema is registered under subject payments.charge_created-value in BACKWARD mode. A developer opens a PR that renames amount to amount_cents. CI calls the registry's compatibility endpoint for that subject with the new schema; the registry evaluates whether a reader on the new schema can parse data written with the old one, finds no field named amount and no alias pointing to it, and returns is_compatible: false. CI fails the build. The developer adds "aliases": ["amount"] to amount_cents, so a new-schema reader can resolve data written under the old field name; CI re-runs, the check passes, and the PR can merge.
Trade-offs and pitfalls
Strict enforcement is safest but slows down producers who need a genuine breaking change (a rename with no clean alias, a field split); the correct escape hatch is a new subject or version, not disabling the check, otherwise the registry stops being trustworthy. A registry only enforces what serializers actually call into: if a team writes raw JSON to a topic without going through the registered serializer, the guarantee is a fiction for that topic. And a registry proves structural compatibility, not semantic correctness; it will not catch a field that keeps its type but silently changes meaning.
New privacy rules restrict which identifiers you can use for modeling. Translate that legal constraint into concrete data-science actions: what access controls change, what alternative feature-engineering strategies would you use (aggregated or anonymized features), how would you quantify and communicate any resulting drop in model accuracy to stakeholders, and what would an exception-request process look like for cases that genuinely need the restricted signal?
Sample Answer
Translate the legal restriction into four concrete moves: change who can access the restricted identifiers at all, replace them in the feature pipeline with aggregated or anonymized substitutes, measure and report the resulting accuracy impact honestly rather than downplaying it, and stand up a narrow exception process for the genuine edge cases that need the restricted signal.
Access controls that change
The restricted identifiers (say, a device ID or a precise home address used previously as a feature) get reclassified to a tighter access tier immediately: revoke the feature pipeline's standing read access to the raw identifier columns, and route any remaining legitimate use (data engineering maintenance, a compliance audit) through the same time-boxed, logged elevated-access process used for other restricted data, rather than a blanket carve-out for the modeling team. This is the first move because it's the one that actually satisfies the legal constraint; the feature-engineering changes below are what keep the model usable once that access is gone.
Alternative feature-engineering strategies
Replace a restricted identifier with a feature that carries useful signal without being the individually-identifying value itself:
- Aggregated features. Instead of a specific device ID, use device-type-level statistics (how common is this device category among past customers), or cohort-level behavioral rates instead of an individual event log tied to the identifier.
- Coarsened, bucketed, or anonymized features. A precise address becomes a broader geographic bucket (postal-code-prefix instead of full address), or an identifier is replaced with an anonymized derivative (a k-anonymity-style generalization, irreversible by design) fine enough to retain regional signal but too coarse to identify an individual.
- Learned embeddings from allowed inputs. Where the restricted identifier was acting as a proxy for behavior, a model can sometimes learn a similar signal from the allowed behavioral features directly (transaction patterns, tenure) rather than a shortcut identifier feature.
The pattern across all three: preserve the population-level signal the identifier used to carry, drop the individual-level specificity that made it restricted.
Quantifying and communicating the accuracy impact
Retrain the model on the compliant feature set and compare against a documented baseline using a held-out test set that both versions are scored against identically:
- Report a concrete metric delta (for example area under the receiver operating characteristic curve, or precision at a fixed operating threshold), not a vague "slightly worse."
- Report it with the actual comparison methodology stated (same test set, same time period, same evaluation metric) so the number is reproducible and not an artifact of a lucky or unlucky split.
- Frame the communication to stakeholders around the trade-off, not just the loss: "the compliant model is X accuracy points lower, and here's what that means in the business metric that matters" (fewer catches at the current threshold, or a shift in the threshold needed to hold recall constant), rather than presenting the number in isolation.
- Where the drop is material, present the threshold-adjustment option explicitly: sometimes the same recall can be recovered by adjusting the classification threshold at the cost of precision elsewhere, which is a genuine mitigation stakeholders should be told about, not a hidden lever.
Exception-request process for cases that genuinely need the restricted signal
Some use cases (a fraud investigation needing the actual device ID, a regulatory reporting requirement) may have a legitimate, narrower legal basis to use the restricted identifier even under the new rule. The process:
- The requester documents the specific legal basis or narrow carve-out that applies (not "the model performs better with it," which is not itself a legal basis).
- A privacy or legal reviewer, not the modeling team itself, approves or denies, since the modeling team has an inherent incentive to want the higher-performing feature back.
- Approved exceptions are scoped narrowly (this specific model, this specific use case) and time-boxed with a required re-review, rather than becoming a permanent blanket exemption once granted.
- Every exception is logged in the same governance record used for other restricted-data access, so an auditor can see the full population of cases where the restricted identifier is still in use and why.
Trade-offs & pitfalls
The most common mistake is treating the accuracy-impact conversation as something to minimize or avoid raising, out of concern that a visible drop looks bad. The opposite approach protects the team better: state the drop plainly with the methodology behind it, because a stakeholder who later discovers an unreported degradation on their own trusts the modeling team far less than one who was told upfront and given a mitigation option.
What is data lineage, and why does it matter for debugging a wrong number, building trust in a dashboard, and supporting a compliance or audit request? Describe the difference between dataset-level and column-level lineage.
Sample Answer
Data lineage is the recorded trail of where a piece of data came from and every transformation it passed through on the way to where you are looking at it now, a map of what fed into what. It matters for three distinct reasons: it lets you trace a wrong number back to its cause instead of guessing, it lets a stakeholder verify a dashboard's number is trustworthy by seeing its provenance rather than taking it on faith, and it lets you answer a compliance or audit request, "show me everything that fed into this reported figure," without manually reconstructing the pipeline's history.
Why it matters: debugging a wrong number
Without lineage, tracing a bad number backward means manually reading pipeline code and asking around. With it, you follow the recorded chain from the dashboard metric back through each transformation to the source tables, narrowing down where the value diverged from expectation directly, often in minutes instead of hours or days of archaeology.
Why it matters: building trust in a dashboard
A stakeholder who can see, even at a summary level, that a revenue number traces back through a specific, named set of transformations to a specific source table trusts it more than an opaque number with no visible provenance. When the number is questioned, "here is exactly where it comes from" is a much stronger answer than "the pipeline is supposed to be correct."
Why it matters: compliance and audit
Regulators or internal auditors asking "show me what fed into this reported figure" need a defensible, complete answer, and reconstructing that by hand for a complex pipeline is slow and error-prone. Captured lineage turns that into a query rather than an investigation, and provides an auditable record even for figures nobody has looked closely at in months.
Dataset-level versus column-level lineage
Dataset-level lineage tracks dependencies at the table or file level, "table C was built from tables A and B," without saying which specific columns of A and B fed which columns of C. It is cheaper to capture and is enough for coarse-grained impact analysis, such as "if table A changes, table C might be affected."
Column-level lineage tracks the dependency down to individual fields, "column revenue in table C is derived specifically from price and quantity in table A, via this transformation," and not from the other twenty columns table A happens to have. It is more expensive to capture, usually requiring parsing the actual transformation logic rather than just job-level metadata, but it gives a precise answer to "what actually feeds this specific number," which dataset-level lineage can only approximate.
Worked example
An executive dashboard shows quarterly revenue dropped 8% quarter over quarter, and the finance team does not believe it. Dataset-level lineage shows the revenue metric comes from a fct_revenue table, itself built from orders and refunds, which narrows the search to two tables but not further. Column-level lineage shows the dashboard's revenue figure specifically traces to orders.amount_cents minus refunds.refund_amount_cents, aggregated by quarter, and that a transformation two steps upstream started applying a status filter differently after a recent change, causing pending orders to be dropped from the current quarter's total but not the prior quarter's, a data artifact rather than a real revenue drop. Because the lineage was captured at column level, this took one query against the lineage graph instead of re-reading every transformation in the pipeline by hand. The same trace, if requested later by an auditor asking how the reported quarterly revenue figure was derived, is already sitting there as a reusable record rather than something that has to be rebuilt from memory.
Trade-offs and pitfalls
Dataset-level lineage is much cheaper to maintain and is often good enough for impact analysis, such as deciding who to notify before a schema change, so jumping straight to column-level everywhere is over-engineering for teams that mainly need the coarser view; column-level lineage earns its cost specifically for high-stakes, frequently-questioned metrics like revenue or compliance-reported figures. The common pitfall is treating lineage as something you can bolt on retroactively for an audit request; if it is not captured continuously as pipelines run, reconstructing it after the fact for a specific number someone is now questioning is exactly the manual archaeology lineage is supposed to replace.
Unlock Full Question Bank
Get access to all 39 Data Governance, Contracts, and Classification interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.