Database Schema
This document describes the PostgreSQL database schema used by the SG Cars Trends platform, including table structures, relationships, and indexing strategies.Entity Relationship Diagram
Table Specifications
Cars Table
Purpose: Stores monthly vehicle registration data from LTA DataMall Table Definition:id: UUID primary key (auto-generated)month: Registration month in YYYY-MM format (e.g., “2024-01”)make: Vehicle manufacturer name (e.g., “TOYOTA”, “BMW”)importer_type: Registration type classificationfuel_type: Fuel type (“Petrol”, “Diesel”, “Electric”, “Hybrid”)vehicle_type: Vehicle category (“Cars”, “Motor cycles”, “Buses”, etc.)number: Number of registrations for the specific combination
- Monthly registration summaries by make
- Fuel type distribution analysis
- Vehicle type breakdowns
- Historical trend analysis
COE Bidding Results Table
Purpose: Stores Certificate of Entitlement bidding exercise results Table Definition:id: UUID primary keymonth: Bidding month (YYYY-MM format)bidding_no: Bidding exercise number (1 or 2 per month)vehicle_class: COE category classificationquota: Number of certificates availablebids_success: Number of successful bidsbids_received: Total number of bids submittedpremium: Winning premium amount in SGD
- Latest bidding results by category
- Premium trend analysis
- Bidding success rate calculations
- Historical premium comparisons
COE Prevailing Quota Premium Table
Purpose: Stores monthly PQP rates for immediate vehicle registration Table Definition:id: UUID primary keymonth: Month in YYYY-MM formatvehicle_class: COE categorypqp: Prevailing Quota Premium rate in SGD
Blog Posts Table
Purpose: Stores LLM-generated blog content with comprehensive metadata Table Definition:id: UUID primary keytitle: Blog post titleslug: URL-friendly identifier (unique)content: Markdown-formatted blog contentmetadata: JSON blob containing tags, reading time, data source info, etc.published_at: Publication timestamp (NULL for drafts)created_at: Creation timestampmodified_at: Last modification timestamp
- Published posts ordered by date
- Posts filtered by tags
- Posts by data month or type
- Blog post analytics
Analytics Table
Purpose: Tracks page views and visitor metrics for performance monitoring Table Definition:id: Auto-incrementing primary keydate: Event timestamp with timezonepathname: Page URL path being accessedreferrer: Referring URL (if available)country: Visitor country (from geolocation)flag: Country flag emojicity: Visitor citylatitude: Geographic latitudelongitude: Geographic longitude
- Page view counts by pathname
- Geographic visitor distribution
- Referrer analysis
- Traffic trends over time
Indexing Strategy
Performance Optimization
Composite Indexes: Created for common multi-column queries(month, make): Cars filtered by month and manufacturer(month, vehicle_class): COE data by month and category(month, bidding_no, vehicle_class): Complex COE queries
- Date/month columns for temporal queries
- Category columns for grouping operations
- Numeric columns for range queries and sorting
Index Maintenance
Automatic Maintenance: PostgreSQL automatically maintains indexes Query Analysis: UseEXPLAIN ANALYZE to verify index usage
Performance Monitoring: Monitor slow queries and add indexes as needed
Data Relationships
Conceptual Relationships
While the schema doesn’t use foreign key constraints, there are logical relationships: Posts → Cars/COE Data: Blog posts are generated from specific month’s dataposts.metadata.data_monthrelates tocars.monthorcoe.monthposts.metadata.data_typeindicates source table (“cars” or “coe”)
- Both tables share
monthandvehicle_classfields - PQP rates complement bidding results for complete COE picture
Data Integrity
Unique Constraints: Blog post slugs must be unique NOT NULL Constraints: Essential fields are required Application-Level Validation: Business logic enforces data consistencyMigration Management
Drizzle ORM Integration
Schema Definition: Tables defined using Drizzle ORM TypeScript schema Migration Generation:pnpm generate creates SQL migration files
Migration Execution: pnpm migrate applies pending migrations
Migration Workflow: