For the ShoeStore project, PostgreSQL was selected as the primary relational database management system (RDBMS). The decision is driven by the following key factors:
- Advanced E-commerce Capabilities: PostgreSQL offers robust support for complex queries, transactions, and concurrency control (MVCC), which are crucial for handling simultaneous cart checkouts and inventory updates in an e-commerce platform.
- Seamless Entity Framework Core Integration: The
Npgsql.EntityFrameworkCore.PostgreSQLprovider is highly optimized. We also utilized theUseSnakeCaseNamingConvention()extension to automatically map C#PascalCaseproperties to PostgreSQL's standardsnake_casecolumns, keeping the database schema clean and standardized. - Security & Data Integrity: PostgreSQL provides excellent data integrity constraints. Combined with our use of
Guidfor exposed IDs (Public IDs), we effectively mitigate Insecure Direct Object Reference (IDOR) vulnerabilities. - Open-Source & Enterprise-Ready: It is a powerful, open-source database that provides enterprise-level features without licensing costs, making it the perfect choice for scalable modern applications.
(Below is the ERD illustrating the relationships between the core entities in the ShoeStore system.)
The database schema is heavily normalized to reduce redundancy and maintain data integrity. The tables are logically grouped into four main domains:
users: The central table for authentication and authorization.- Stores
email, hashedpassword, androle(Customer/Admin). - Uses a
public_id(UUID) exposed to the frontend instead of the primary key to enhance security.
- Stores
user_refresh_tokens: Manages JWT refresh tokens for maintaining long-lived user sessions securely.user_restore_passwords: Tracks OTPs and expiration times for the "Forgot Password" flow.
To handle a diverse inventory of shoes (different colors and sizes), the product catalog implements a hierarchical structure:
products: Contains the base information of a shoe model (e.g., Name, Description, Brand, Base Price).colors: A lookup table defining available colors.product_variants: Represents a specific purchasable combination of aProduct,Color, andSize. It links aProductto aColorand aproduct_sizeentry, and stores inventory-related fields such asstockand currentprice, along with any variant-specific image URLs.product_sizes: A lookup table of available shoe sizes (e.g., 38, 39, 40). Each row defines a single size value that can be reused across products and variants; it does not track stock itself.
cart_items: Acts as a temporary holding area for users' desired items. It maps aUserto a specificProductVariant(product + color + size) along with the desiredQuantity.invoices: Represents a finalized customer order. Tracks theTotalAmount, shipping details, and the overallInvoiceStatus(e.g., Pending, Processing, Shipped, Cancelled).invoice_details: The line items of an invoice. Each line references the chosenProductVariantand freezes theUnitPriceat the time of purchase to ensure historical accuracy even if the base product price changes later.payments: Records the transaction details (Payment Method, Payment Status, Transaction ID) linked to a specificInvoice.
vouchers: Stores discount campaigns (Discount percentage, Max discount amount, Expiration date).user_vouchers: A mapping table that tracks which user has collected or used which voucher, preventing multi-use abuse.