The Analyst Who Saw the Salary Data

A hard Pipeline Design interview practice problem on DataDriven. Design the pipeline on the canvas: sources, transforms, storage and checks, then get feedback on it.

Domain
Pipeline Design
Difficulty
hard
Seniority
L5
Asked in
Epsilon3

Problem

Five business units of very different sensitivity share one flat lake store behind a single reader role, and the platform lead just learned an analyst read another unit's files directly. Redesign the lake so each unit gets its own isolated store, while about 300 analysts and the few pre-approved cross-unit reads keep working.

Two incidents. One shared lake. The access model was never designed, just assumed.

Business requirements

Worked solution and explanation

Why this problem exists in real interviews

Five business units with different sensitivity levels share a lake, and there have already been two cross-unit exposures. This is a tenancy-boundary problem dressed up as a storage cleanup. The trap is bolting application-layer filtering onto data that is still commingled. What actually holds is per-unit storage isolation, with each write boundary set at ingest.

The default reach is to keep everything in one store and rely on a single shared reader role plus query-layer filters to keep teams apart. Analysts then read across boundaries by opening files directly, which is how a marketing analyst ends up with a salary file. A single loader with broad write permissions is how one misconfigured pipeline writes into the HR area.


Walk the requirements

Step 1: Give each unit its own store

HR, finance and marketing each land in their own object store, and the storage policy enforces read access there. An analyst who tries to open HR files fails because storage denies the request, not because a query filter happened to catch it. Without per-unit stores, the boundary lives only in the query layer, and both prior incidents went around that layer.

Step 2: Serve cross-unit reads through a column-governed engine

Marketing legitimately needs the customer dimension and operations needs finance order data. Granting either team broad access to the other unit's store is exactly what failed before. Instead, the query engine exposes only the approved columns to the cross-unit role, and the underlying data stays locked. Analysts reach every store through this engine and never directly. Without the engine, the column boundary has nowhere to live.

Step 3: Give each unit store its own write path

Each unit has its own loader, and that loader's credentials can write to one store only. A loader pointed at the wrong store fails at the permission boundary, not at code review. One shared loader with broad write access turns a one-line config error into data landing in another unit's store. Separate loaders keep the blast radius to one unit.


The shape that fits

Each unit has its own loader writing to its own object store. Analysts reach every store only through the column-governed query engine, which returns just the approved columns.
  • unit_source_systems (source)
  • hr_loader (transform, Spark)
  • finance_loader (transform, Spark)
  • marketing_loader (transform, Spark)
  • hr_store (storage, object storage)
  • finance_store (storage, object storage)
  • marketing_store (storage, object storage)
  • column_governed_query_engine (storage, warehouse)
  • analyst_dashboards (consumer, dashboard)
  • unit_source_systems -> hr_loader
  • unit_source_systems -> finance_loader
  • unit_source_systems -> marketing_loader
  • hr_loader -> hr_store
  • finance_loader -> finance_store
  • marketing_loader -> marketing_store
  • hr_store -> column_governed_query_engine
  • finance_store -> column_governed_query_engine
  • marketing_store -> column_governed_query_engine
  • column_governed_query_engine -> analyst_dashboards

Common follow-up questions