Open Threads
A medium Data Modeling interview practice problem on DataDriven. Design the schema on the canvas: tables, keys and relationships, then get feedback on it.
- Domain
- Data Modeling
- Difficulty
- medium
- Seniority
- L4
- Asked in
- Microsoft
Problem
We need to track how much time employees spend in each application. HR wants daily summaries of time-per-employee-per-application, and wants to flag any employee spending more than 10 hours/day in a single application. Design the schema to capture this data.
Every minute tracked. Every app accounted for.
Worked solution and explanation
Why this problem exists in real interviews
This probes whether a candidate models open-ended sessions safely and handles midnight-spanning windows. Both traps kill naive time-tracking schemas the moment the data hits production, and interviewers look for candidates who surface them without being asked.
Break down the requirements
Step 1: Declare the session grain
app_sessions is one row per continuous use of an application by an employee. Start and end timestamps define the session; null end means the session is still open or was abandoned.
Step 2: Make end_ts nullable
An app that crashes never emits an end event. If the column is non-null, the ingest job either loses the session or fabricates a fake end. Nullable plus a scheduled cleanup job (close sessions idle for 6 hours) is the honest design.
Step 3: Handle midnight spans in the rollup
A session from 23:45 to 00:30 contributes 15 minutes to one day and 30 minutes to the next. The daily rollup job must clip session intervals to day boundaries, or the 10-hour flag triggers on the wrong day.
Step 4: Keep employees and applications as dimensions
Conformed dimensions let HR slice by department, office, or application without rebuilding the fact. The session fact carries only surrogate keys and the two timestamps.
The solution
Below is one conceptually sound approach: raw sessions with nullable end, dimensional context on employees and applications, and daily rollups computed downstream.
- employees: employee_id INT PK, full_name TEXT, department TEXT, hire_date DATE
- applications: application_id INT PK, app_name TEXT, vendor TEXT, category TEXT
- app_sessions: session_id BIGINT PK, employee_id INT FK, application_id INT FK, start_ts TIMESTAMP, end_ts TIMESTAMP, device_id TEXT
- employees references app_sessions
- applications references app_sessions
The analysis pattern
WITH clipped AS (
SELECT
s.employee_id,
s.application_id,
d.day,
GREATEST(s.start_ts, d.day::TIMESTAMPTZ) AS clip_start,
LEAST(COALESCE(s.end_ts, NOW()), (d.day + INTERVAL '1 day')::TIMESTAMPTZ) AS clip_end
FROM app_sessions s
CROSS JOIN LATERAL generate_series(
DATE(s.start_ts),
DATE(COALESCE(s.end_ts, NOW())),
INTERVAL '1 day'
) AS d(day)
)
SELECT
employee_id,
application_id,
day,
SUM(EXTRACT(EPOCH FROM (clip_end - clip_start)) / 60) AS minutes_used
FROM clipped
GROUP BY employee_id, application_id, day
HAVING SUM(EXTRACT(EPOCH FROM (clip_end - clip_start)) / 3600) > 10Trade-offs and alternatives
- Raw sessions plus daily clipped rollup
- Raw data is preserved, rollups are recomputable, cleanup is a policy layer. Cost: rollup SQL is heavier because intervals are clipped per day.
- Minute-bucket fact table
- Emit a row per minute of activity so rollups are trivial
GROUP BYs. Cost: volume explodes by 60x, and the ingest path has to debounce duplicate activity.
Common follow-up questions
- How do you detect a session that legitimately exceeds 24 hours on an always-on dashboard? (Tests whether the cleanup policy accommodates a known exception pattern.)
- What if an employee works across two time zones in one day? (Tests whether rollups are in local time or UTC and how that affects the 10-hour threshold.)
- How would you detect suspicious overlap where one employee appears in two sessions at once? (Tests an integrity check for concurrent sessions on the same employee.)
- At 500k employees, how do you keep the daily rollup fresh for a real-time dashboard? (Tests incremental rollup strategies and whether it moves to streaming.)