Skip to main content

Data Warehouse Design: Star Schema for ERP & eCommerce Analytics

Learn dimensional modeling with star schema for ERP and eCommerce analytics covering fact tables, dimension tables, ETL patterns, and query optimization.

E
ECOSIRE Research and Development Team
|March 15, 202612 min read2.4k Words|

Your ERP database is optimized for transactions --- inserting orders, updating inventory, processing payments. Your eCommerce platform is optimized for serving product pages and processing checkouts.

Part of our Data Analytics & BI series

Read the complete guide

Your ERP database is optimized for transactions --- inserting orders, updating inventory, processing payments. Your eCommerce platform is optimized for serving product pages and processing checkouts. Neither is optimized for answering the questions that drive business decisions: Which product categories are most profitable after returns? Which customer segments have growing lifetime value? Where are the bottlenecks in our supply chain?

That gap is what a data warehouse fills. And the star schema is the design pattern that makes analytical queries fast, intuitive, and maintainable.

Key Takeaways

  • Star schema separates business metrics (facts) from descriptive context (dimensions), making queries intuitive and fast
  • ERP and eCommerce analytics typically need four to six fact tables and eight to twelve dimension tables to cover core business questions
  • ETL pipelines should use incremental loading with slowly changing dimensions to handle historical analysis without reprocessing all data
  • A well-designed star schema reduces query complexity by 60 to 80 percent compared to querying normalized operational databases directly

Why Not Query the ERP Directly?

Before investing in a separate data warehouse, many companies try to run analytical queries against their operational database. This fails for three reasons.

Performance. Analytical queries scan millions of rows, compute aggregations, and join many tables. Running these against the production database slows down the ERP for every user. A report that scans six months of order data can lock tables and degrade checkout performance on your Shopify store.

Complexity. Operational databases are normalized --- designed to minimize data redundancy. A simple question like "total revenue by product category by month" might require joining eight tables in Odoo's PostgreSQL database. In a star schema, the same query joins two tables.

History. Operational systems overwrite data. When a customer changes their address, the old address is gone. When a product is recategorized, historical reports retroactively change. A data warehouse preserves history through slowly changing dimensions.

Multi-source. Mid-market companies typically run three to seven systems that contain business data. The data warehouse consolidates all of them. Our guide to ETL pipelines for ERP data covers extraction and loading in detail.


Star Schema Fundamentals

A star schema organizes data into two types of tables: fact tables and dimension tables. Fact tables sit at the center (the star's body), and dimension tables surround them (the star's points).

Fact Tables

Fact tables store measurable business events --- things that happened. Each row represents one event at the lowest meaningful grain.

Characteristics:

  • Contain numeric measures (quantity, amount, duration, count)
  • Contain foreign keys to dimension tables
  • Are typically the largest tables in the warehouse
  • Grow continuously as new events occur
  • Should be at the finest grain that supports business questions

Dimension Tables

Dimension tables store descriptive context --- the who, what, where, when, and how of business events.

Characteristics:

  • Contain textual attributes and hierarchies
  • Are relatively small (thousands to millions of rows, not billions)
  • Change slowly over time
  • Are denormalized for query simplicity
  • Provide the labels, filters, and groupings for reports

The Star Shape

                    Dim: Customer
                         |
    Dim: Product ---  Fact: Sales  --- Dim: Time
                         |
                    Dim: Location

A query like "total revenue by product category by quarter by region" joins the sales fact table to three dimension tables. No subqueries, no complex nested joins --- just straightforward star joins.


Designing Fact Tables for ERP and eCommerce

A typical mid-market company running Odoo ERP and Shopify eCommerce needs four to six fact tables to cover the core analytical use cases.

Fact: Sales

The sales fact table is the cornerstone. Each row represents one line item on a sales order.

ColumnTypeDescription
sale_keyBIGINTSurrogate key
date_keyINTFK to Dim: Time
customer_keyINTFK to Dim: Customer
product_keyINTFK to Dim: Product
location_keyINTFK to Dim: Location
channel_keyINTFK to Dim: Channel
salesperson_keyINTFK to Dim: Employee
quantityDECIMALUnits sold
unit_priceDECIMALPrice per unit
discount_amountDECIMALDiscount applied
tax_amountDECIMALTax charged
net_amountDECIMALRevenue after discount, before tax
cost_amountDECIMALCost of goods sold
gross_marginDECIMALnet_amount minus cost_amount

Grain: One row per order line item per day.

Fact: Inventory

Tracks inventory levels as periodic snapshots rather than events.

ColumnTypeDescription
inventory_keyBIGINTSurrogate key
date_keyINTFK to Dim: Time (snapshot date)
product_keyINTFK to Dim: Product
warehouse_keyINTFK to Dim: Warehouse
quantity_on_handDECIMALCurrent stock
quantity_reservedDECIMALAllocated to orders
quantity_availableDECIMALOn hand minus reserved
reorder_pointDECIMALMinimum before reorder
stock_valueDECIMALQuantity times unit cost

Grain: One row per product per warehouse per day.

Fact: Production

For manufacturing companies, the production fact tracks work orders.

ColumnTypeDescription
production_keyBIGINTSurrogate key
date_keyINTFK to Dim: Time
product_keyINTFK to Dim: Product
workcenter_keyINTFK to Dim: Workcenter
planned_quantityDECIMALTarget output
actual_quantityDECIMALActual output
scrap_quantityDECIMALWaste
planned_duration_hrsDECIMALExpected time
actual_duration_hrsDECIMALActual time
yield_rateDECIMALactual / planned quantity

Grain: One row per work order per product per day.

Additional Fact Tables

  • Fact: Purchases --- procurement spend by vendor, product, and time.
  • Fact: Support Tickets --- ticket volume, response time, resolution time by agent, customer, and category.
  • Fact: Web Traffic --- page views, sessions, conversions by page, source, and campaign. Useful for marketing attribution analysis.

Designing Dimension Tables

Dimension tables provide the context that makes fact table numbers meaningful. The key principle is denormalization --- storing redundant data to simplify queries.

Dim: Time

The time dimension is present in every star schema. Pre-calculate calendar attributes to avoid complex date functions in queries.

ColumnExamplePurpose
date_key20260315Integer key (YYYYMMDD)
full_date2026-03-15Date value
day_of_weekSundayGrouping
day_of_month15Grouping
week_of_year11Grouping
month_nameMarchGrouping
month_number3Sorting
quarterQ1Grouping
year2026Grouping
fiscal_quarterFQ4Fiscal year alignment
fiscal_yearFY2026Fiscal year alignment
is_weekendTRUEFiltering
is_holidayFALSEFiltering

Dim: Customer

Denormalize customer attributes from the CRM, accounting, and eCommerce systems into a single dimension.

ColumnDescription
customer_keySurrogate key
customer_idNatural key (Odoo ID)
customer_nameFull name
customer_emailEmail address
customer_segmentEnterprise, SMB, Individual
industryManufacturing, Retail, Services
countryCountry name
regionGeographic region
cityCity
acquisition_sourceOrganic, Paid, Referral
acquisition_dateFirst purchase date
rfm_segmentChampion, Loyal, At-Risk
lifetime_value_tierHigh, Medium, Low

The rfm_segment and lifetime_value_tier columns are calculated fields derived from RFM analysis, updated periodically by the ETL pipeline.

Dim: Product

ColumnDescription
product_keySurrogate key
product_idNatural key
product_nameDisplay name
skuStock keeping unit
category_l1Top-level category
category_l2Sub-category
category_l3Sub-sub-category
brandBrand name
unit_costCurrent standard cost
list_priceCurrent list price
weightShipping weight
is_activeCurrently for sale

Slowly Changing Dimensions

When a customer moves from New York to London, what should the data warehouse do? The answer depends on the business question.

Type 1: Overwrite

Replace the old value with the new value. The customer's city becomes London, and all historical orders now show London. Use this when historical accuracy of the attribute does not matter.

Type 2: Add New Row

Create a new row for the customer with the new city, an effective date, and an expiration date. Historical orders still point to the old row (New York), and new orders point to the new row (London). This is the most common approach for attributes that affect analysis --- customer segment, employee department, product category.

customer_keycustomer_idcityeffective_dateexpiration_dateis_current
1001CUST-042New York2024-01-152026-02-28FALSE
1002CUST-042London2026-03-019999-12-31TRUE

Type 3: Add New Column

Store both old and new values in separate columns. Useful when you need to compare before and after but do not need full history. Less common in practice.

For mid-market companies, use Type 2 for customer segment, employee department, product category, and geographic attributes. Use Type 1 for everything else to keep the warehouse simple.


ETL Design Patterns

The ETL (Extract, Transform, Load) process moves data from source systems into the warehouse. Design patterns that work well for ERP and eCommerce data include the following.

Incremental Loading

Rather than reloading all data on every run, track the last successfully loaded timestamp and only process records modified since then. Odoo's write_date field and Shopify's updated_at parameter make this straightforward.

1. Query source: SELECT * FROM sale_order_line WHERE write_date > last_load_timestamp
2. Transform: Map source fields to warehouse columns, look up dimension keys
3. Load: INSERT new rows, UPDATE changed rows (upsert)
4. Update: Set last_load_timestamp to current run start time

Surrogate Key Management

Dimension tables use surrogate keys (auto-incrementing integers) instead of natural keys (Odoo IDs, Shopify IDs). This decouples the warehouse from source system key formats and handles multi-source consolidation where different systems have conflicting ID schemes.

Late-Arriving Dimensions

Sometimes a fact record arrives before the corresponding dimension record --- an order references a new customer who has not been synced yet. Handle this with a placeholder dimension row that gets updated when the full dimension record arrives.

Refresh Scheduling

Data TypeRefresh FrequencyRationale
Sales transactionsEvery 15-60 minutesNear-real-time revenue tracking
Inventory snapshotsEvery 4-6 hoursBalance accuracy vs. database load
Customer dimensionsDailyChanges are infrequent
Product dimensionsDailyChanges are infrequent
Financial dataDaily (after close)Depends on accounting workflows
Marketing dataEvery 1-4 hoursCampaign optimization needs fresher data

For real-time requirements, see our guide to streaming analytics.


Query Performance Optimization

A well-designed star schema already performs well because of its simple join patterns. Additional optimizations include the following.

Indexes. Create indexes on all dimension foreign keys in fact tables and on commonly filtered dimension attributes (date ranges, customer segments, product categories).

Materialized views. Pre-aggregate common queries: daily revenue by product category, weekly inventory levels by warehouse, monthly customer acquisition by channel. Refresh materialized views after each ETL load.

Partitioning. Partition large fact tables by date (monthly or quarterly). Queries that filter by date range scan only the relevant partitions.

Column statistics. Keep PostgreSQL statistics up to date with ANALYZE after bulk loads so the query planner makes optimal decisions.

These optimizations support the self-service BI experience where business users run ad-hoc queries without performance concerns.


Frequently Asked Questions

How big does the company need to be to justify a data warehouse?

There is no minimum size, but the investment becomes worthwhile when you have multiple data sources that need to be combined for analysis, when operational database queries are slowing down production systems, or when you spend more than 10 hours per week on manual data gathering and report creation. Most companies with 30 or more employees and at least two systems (ERP plus eCommerce) benefit from a warehouse.

Should we use a cloud data warehouse like Snowflake or BigQuery?

For mid-market companies, PostgreSQL handles most analytical workloads well and costs significantly less. Cloud warehouses like Snowflake become attractive when your data exceeds 1 TB, when you need to separate compute from storage for cost optimization, or when you have complex data sharing requirements across organizations. Start with PostgreSQL and migrate when you outgrow it.

How long does it take to build a data warehouse?

A minimum viable warehouse with one fact table (sales), four dimension tables, and an ETL pipeline connecting Odoo and Shopify takes four to eight weeks for an experienced team. Adding fact tables, slowly changing dimensions, and data quality monitoring takes another four to eight weeks per fact table. Plan for three to six months for a comprehensive warehouse covering all major business areas.


What Is Next

A well-designed star schema is the foundation for every analytics capability --- from self-service dashboards to predictive models to embedded analytics. It is part of a broader BI strategy that transforms how your company makes decisions.

ECOSIRE builds data warehouses and analytics pipelines for companies running Odoo, Shopify, and GoHighLevel. Our Odoo consultancy team designs warehouse schemas tailored to your business model, and our OpenClaw AI services layer predictive analytics on top.

Contact us to discuss your data warehouse architecture.


Published by ECOSIRE --- helping businesses scale with AI-powered solutions across Odoo ERP, Shopify eCommerce, and OpenClaw AI.

E

Written by

ECOSIRE Team

Technical Writing

The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.

ECOSIRE

Transform Your Business with Odoo ERP

Expert Odoo implementation, customization, and support to streamline your operations.