Data Modeling with Supabase
Overview
This guide covers the approach to data modeling in the MOOD MNKY ecosystem, focusing on Supabase’s PostgreSQL foundation and how we structure data for optimal performance, scalability, and type safety.Core Principles
Our data modeling approach follows these key principles:- Schema-first development: Define database schemas explicitly before implementing application logic
- Strong typing: Leverage TypeScript for type-safe data access across the application
- Relational integrity: Use PostgreSQL’s robust relational features for data consistency
- Performance optimization: Design schemas with query patterns in mind
- Security by design: Apply Row Level Security (RLS) policies from the start
Directory Structure
Data models in the MOOD MNKY ecosystem are organized as follows:Schema Definitions
Database schemas are defined in SQL files located in/data/schemas/. Each table has its own file named after the table.
Example Schema
TypeScript Models
TypeScript models provide type-safe access to database tables. Each model is defined in its own file in/data/models/.
Example Model
Common Data Patterns
User Authentication and Profiles
We separate authentication data (managed by Supabase Auth) from user profile data:Many-to-Many Relationships
For many-to-many relationships, we use junction tables with composite primary keys:Hierarchical Data
For hierarchical data, we use either adjacency lists or path enumeration:Row Level Security (RLS)
All tables should have appropriate RLS policies defined to control access:Schema Evolution
When evolving schemas, follow these guidelines:- Create a new migration file using
supabase migration new - Make additive changes when possible (add columns, tables)
- For destructive changes, use a multi-step migration approach:
- Add new structure
- Migrate data
- Remove old structure (in a later migration)
- Update TypeScript models to reflect schema changes
Type Generation
To maintain type safety, generate TypeScript types from your database schema:Performance Considerations
Indexing Strategy
Create indexes for columns that are frequently used in:- WHERE clauses
- JOIN conditions
- ORDER BY clauses
Pagination
For large datasets, implement keyset-based pagination instead of offset pagination:Best Practices
- Use UUIDs for primary keys: Provides better security and distribution for large datasets
- Add created_at/updated_at timestamps: Helps with debugging and audit trails
- Normalize data appropriately: Balance between normalization and query performance
- Use appropriate data types: Leverage PostgreSQL’s rich type system
- Document complex schemas: Add comments to explain relationships and constraints
- Version control schema changes: Keep all migrations in version control
- Test migrations: Verify that migrations work correctly before deployment
- Use transactions: Wrap related changes in transactions for atomicity