System Design · medium · Reported at Shopify

Design a data warehouse schema for an e-commerce company.

Asked in Analytics Engineer interviews, in the System Design round.

Short answer

Star schema: fact_orders plus dimensions (user, product, date, geo), with slowly changing dimensions where attributes drift.

A star schema with one order fact table and four dimensions fact_orders customer_key product_key date_key store_key quantity, amount dim_customer name, segment dim_product title, category dim_date day, month, quarter dim_store region, country
One fact table of measures, joined to dimensions on a single key each.

How to answer it

Requirements first

Ask what questions it has to answer before choosing a shape. Revenue by category and month, repeat purchase rate, cohort retention, inventory turns: those determine the grain and the dimensions. Then ask about history, because "what segment was this customer in when they ordered" decides whether you need Type 2 dimensions.

Architecture

A star schema, as in the diagram above. One fact table at the centre holding the measures and the foreign keys, with dimension tables around it.

fact_order_items          grain: ONE ROW PER ORDER LINE
  order_id, line_id
  customer_key, product_key, date_key, store_key
  quantity, unit_price, discount, net_amount

dim_customer   (Type 2: valid_from, valid_to, is_current)
dim_product    (Type 2 if price or category changes matter)
dim_date       (calendar attributes, fiscal periods, holiday flags)
dim_store

Grain is the first decision

Declare it in one sentence and write it down: one row per order line. Everything else follows. Mixing grains in a fact table, an order-level shipping cost stored on every line, is the single most common way these designs break, because the shipping cost then gets counted once per line.

If you genuinely need both, use two fact tables at different grains rather than one confused one.

Fact table types

Transaction    one row per event. Orders, clicks. The default.
Periodic       one row per entity per period. Daily inventory balance.
Accumulating   one row per process, updated as it progresses. Order to
               delivery, with milestone timestamps.

Tradeoffs

Key points

FAQ

The 30-second answer

I would start by asking what questions it has to answer and whether history matters, because those decide the grain and whether the dimensions need to be Type 2.
Then a star schema: one fact table for order lines holding the foreign keys and the measures, quantity, price and net amount, with dimensions for customer, product, date and store around it.
The first thing I would write down is the grain, one row per order line, because everything follows from it. The classic failure is mixing grains, putting an order-level shipping cost on every line, which then gets counted once per line. If both grains are genuinely needed that is two fact tables, not one. And where customer attributes change over time I would make that dimension Type 2 and join on the order timestamp.

In the interview

Practice this for real