
schema-architect
by mavric
Mavric AI Toolchain - AI-assisted SaaS development
SKILL.md
name: schema-architect description: Designs database schemas with multi-tenancy, relationships, and best practices. Triggers when user needs to design data model, create entities, or plan database structure.
Schema Architect
I design robust, scalable database schemas optimized for SaaS applications with multi-tenancy built in.
What I Create
1. Entity Definitions
For each entity in your system:
- Entity name and purpose
- Fields with types and constraints
- Relationships to other entities
- Indexes for performance
- Validation rules
2. Multi-Tenancy Strategy
- Organization (tenant) entity
- Org-scoped data isolation
- Proper foreign keys to org
- Row-level security patterns
3. Apso Schema File
Complete .apsorc file ready to use:
{
"service": "your-service",
"entities": {
"Organization": { ... },
"User": { ... },
"YourEntity": { ... }
}
}
4. Entity Relationship Diagram
ASCII or Mermaid diagram showing:
- All entities
- Relationships (one-to-many, many-to-many)
- Cardinality
- Foreign keys
5. Data Flow Documentation
- How data moves through the system
- Common query patterns
- Performance considerations
Core Patterns I Use
Standard SaaS Entities
I always include these foundation entities:
Organization (Tenant)
id(UUID, PK)name(string, required)slug(string, unique, required)billing_email(string)stripe_customer_id(string, nullable)subscription_status(enum)created_at,updated_at(timestamps)
User
id(UUID, PK)email(string, unique, required)name(string)avatar_url(string, nullable)organization_id(UUID, FK → Organization, required)role(enum: admin, member, viewer)created_at,updated_at
Subscription
id(UUID, PK)organization_id(UUID, FK → Organization, unique)stripe_subscription_id(string, unique)plan_id(string, required)status(enum: active, canceled, past_due, trialing)current_period_end(timestamp)created_at,updated_at
AuditLog
id(UUID, PK)organization_id(UUID, FK → Organization)user_id(UUID, FK → User, nullable)action(string, required)resource_type(string)resource_id(UUID)ip_address(string)user_agent(string)created_at
File
id(UUID, PK)organization_id(UUID, FK → Organization)uploaded_by(UUID, FK → User)filename(string, required)s3_key(string, required)mime_type(string)size_bytes(integer)created_at
Multi-Tenancy Rules
Every product-specific entity MUST:
- Have
organization_idforeign key - Include org_id in unique constraints
- Be filtered by org_id in queries
- Have proper indexes on org_id
Example:
// ✅ Good - Multi-tenant aware
projects:
- name: string (required)
- organization_id: uuid (FK → organizations, required)
- created_by: uuid (FK → users, required)
- status: enum(active, archived)
indexes:
- [organization_id, created_at]
unique_constraints:
- [organization_id, name] // Name unique per org, not globally
Design Process
Step 1: Entity Discovery
I'll ask you:
- What are the main "things" in your system?
- What data do you need to track?
- What are the user actions?
Common entities by domain:
- Project Management: Project, Task, Milestone, Comment
- E-Commerce: Product, Order, Cart, Payment
- CMS: Post, Page, Media, Category
- CRM: Contact, Deal, Activity, Note
Step 2: Relationship Mapping
For each entity pair, I determine:
- One-to-one
- One-to-many
- Many-to-many (via junction table)
Example:
Organization → User (one-to-many)
Organization → Project (one-to-many)
Project → Task (one-to-many)
User ←→ Project (many-to-many via ProjectMember)
Step 3: Field Definition
For each entity, I define:
- Required vs optional fields
- Data types (string, number, boolean, enum, JSON, timestamp)
- Constraints (unique, min/max, pattern)
- Default values
Step 4: Optimization
I add:
- Indexes for common queries
- Computed fields (if needed)
- Soft delete flags (deleted_at)
- Timestamps (created_at, updated_at)
Step 5: Validation
I check:
- ✅ Every entity has organization_id (except Organization, User, Session)
- ✅ Foreign keys are correct
- ✅ No circular dependencies
- ✅ Proper cascade deletes
- ✅ Indexes on frequently queried fields
Output Format
Apso .apsorc Schema
{
"service": "your-service-name",
"database": {
"provider": "postgresql",
"multiTenant": true
},
"entities": {
"Organization": {
"fields": {
"id": { "type": "uuid", "primary": true },
"name": { "type": "string", "required": true },
"slug": { "type": "string", "unique": true, "required": true },
"billing_email": { "type": "string" },
"stripe_customer_id": { "type": "string" },
"created_at": { "type": "timestamp", "default": "now()" },
"updated_at": { "type": "timestamp", "default": "now()" }
}
},
"YourEntity": {
"fields": {
"id": { "type": "uuid", "primary": true },
"organization_id": {
"type": "uuid",
"required": true,
"references": "Organization.id"
},
"name": { "type": "string", "required": true },
"status": {
"type": "enum",
"values": ["active", "archived"],
"default": "active"
},
"created_at": { "type": "timestamp", "default": "now()" },
"updated_at": { "type": "timestamp", "default": "now()" }
},
"indexes": [
["organization_id", "created_at"],
["organization_id", "status"]
],
"unique": [
["organization_id", "name"]
]
}
}
}
Entity Relationship Diagram
┌─────────────────┐
│ Organization │
│ (Tenant) │
└────────┬────────┘
│ 1:N
├─────────────────┐
│ │
▼ ▼
┌─────────────┐ ┌──────────────┐
│ User │ │ Project │
└──────┬──────┘ └──────┬───────┘
│ 1:N │ 1:N
│ │
▼ ▼
┌─────────────┐ ┌──────────────┐
│ AuditLog │ │ Task │
└─────────────┘ └──────────────┘
Best Practices I Follow
Data Modeling
✅ Normalize - Reduce data duplication ✅ Foreign Keys - Enforce referential integrity ✅ Indexes - Add for common query patterns ✅ Enums - Use for fixed sets of values ✅ Timestamps - Always include created_at, updated_at
Multi-Tenancy
✅ Org-First - Organization_id on every tenant-scoped table ✅ Proper Indexes - Include org_id in composite indexes ✅ Cascade Rules - Define what happens on delete ✅ Unique Constraints - Scope to organization
Security
✅ No PII in Logs - Exclude sensitive fields ✅ Soft Deletes - Use deleted_at for audit trails ✅ Access Control - Role-based permissions
Common Patterns
Many-to-Many Relationship
// Users can be members of multiple projects
// Projects can have multiple users
ProjectMember (junction table):
- id: uuid (PK)
- organization_id: uuid (FK → Organization)
- project_id: uuid (FK → Project)
- user_id: uuid (FK → User)
- role: enum(owner, editor, viewer)
- created_at: timestamp
unique: [project_id, user_id]
indexes: [[project_id], [user_id]]
Hierarchical Data
// Categories with parent-child relationships
Category:
- id: uuid (PK)
- organization_id: uuid (FK → Organization)
- name: string (required)
- parent_id: uuid (FK → Category, nullable)
- level: integer (for fast queries)
- path: string (e.g., "/1/5/12" for materialized path)
- created_at: timestamp
Polymorphic Associations
// Comments that can be on multiple entity types
Comment:
- id: uuid (PK)
- organization_id: uuid (FK → Organization)
- user_id: uuid (FK → User)
- commentable_type: enum(project, task, document)
- commentable_id: uuid
- content: text
- created_at: timestamp
indexes: [[commentable_type, commentable_id]]
When to Use Me
- ✅ Starting a new project
- ✅ Adding new features that need entities
- ✅ Refactoring existing schema
- ✅ Migrating from monolith to microservices
- ✅ Designing data model before coding
Ready?
Tell me about your application and the data you need to track. I'll design a robust, scalable schema optimized for SaaS with multi-tenancy built in.
What entities do you need in your system?
スコア
総合スコア
リポジトリの品質指標に基づく評価
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
レビュー
レビュー機能は近日公開予定です