Convex Database Schema
Complete reference for the Dashtray database schema.Overview
Dashtray uses Convex as its serverless database and backend. The schema is defined insrc/convex/schema.ts and includes tables for projects, integrations, metrics, dashboards, alerts, and more.
Schema Design Principles
- Type-safe: All fields are strongly typed with Convex validators
- Indexed: Common query patterns are optimized with indexes
- Normalized: Related data is properly linked with IDs
- Timestamped: All tables include creation timestamps
- Soft deletes: Status fields used instead of hard deletes where appropriate
Core Tables
projects
Stores project information and subscription details.by_slug: Fast lookup by slugby_owner: Find all projects for a userby_subscription_tier: Query by tierby_subscription_status: Query by status
projectMembers
Stores team member relationships and roles.by_project: Get all members for a projectby_user: Get all projects for a userby_project_and_user: Check membershipby_status: Query by status
connections
Stores integration connections and credentials.by_project: Get all connections for a projectby_service: Query by service typeby_status: Query by statusby_project_and_service: Check if service is connected
metrics
Stores time series metric data from integrations.by_project: Get all metrics for a projectby_connection: Get metrics for a connectionby_timestamp: Query by timeby_project_and_metric: Get specific metric for a projectby_project_and_timestamp: Time-based queries for a projectby_metric_and_timestamp: Time series for a specific metric
dashboards
Stores dashboard configurations.by_project: Get all dashboards for a projectby_slug: Lookup by slugby_type: Query by typeby_project_and_type: Get dashboards of a specific type for a project
widgets
Stores widget configurations for dashboards.by_dashboard: Get all widgets for a dashboardby_project: Get all widgets for a project
bookmarks
Stores external service bookmarks.by_project: Get all bookmarks for a project
alerts
Stores alert configurations.by_project: Get all alerts for a projectby_enabled: Query enabled alerts
alertLogs
Stores alert trigger history.by_alert: Get logs for an alertby_project: Get all logs for a projectby_triggered_at: Query by time
auditLogs
Stores audit trail for Scale+ users.by_project: Get all logs for a projectby_user: Get logs for a userby_created_at: Query by timeby_project_and_created_at: Time-based queries for a project
aiConversations
Stores AI chat conversations.by_project: Get all conversations for a projectby_user: Get conversations for a userby_project_and_user: Get user’s conversations in a project
userSettings
Stores user-specific settings (AI keys, preferences).by_user: Get settings for a user
apiKeys
Stores API keys for Scale+ users.by_project: Get all keys for a projectby_key_hash: Authenticate API requestsby_created_by: Get keys created by a user
apiUsage
Tracks API usage for rate limiting.by_project: Get usage for a projectby_api_key: Get usage for a keyby_timestamp: Query by timeby_project_and_timestamp: Time-based queries for a project
Related Schemas
Better Auth Tables
Authentication tables are defined insrc/convex/betterAuth/schema.ts:
user: User accountssession: Active sessionsaccount: OAuth accountsverification: Email verification tokens
DodoPayments Tables
Billing tables are managed by the DodoPayments Convex component:- Customers
- Subscriptions
- Payments
- Invoices
Data Retention
Free Tier
- Metrics: 3 days
- Alert logs: 3 days
- AI conversations: 3 days
- Audit logs: Not available
Pro+ Tiers
- Metrics: Unlimited
- Alert logs: Unlimited
- AI conversations: Unlimited
- Audit logs: Unlimited (Scale+ only)
Best Practices
Querying
- Use indexes: Always use the appropriate index for your query
- Filter efficiently: Apply filters after index queries
- Limit results: Use
.first()or.take(n)when appropriate - Paginate: Use cursor-based pagination for large result sets
Writing
- Validate input: Use Convex validators in function args
- Check permissions: Verify user has access before mutations
- Update timestamps: Always update
updatedAton modifications - Soft delete: Use status fields instead of deleting records
Performance
- Batch operations: Group related mutations
- Avoid N+1 queries: Fetch related data efficiently
- Cache when appropriate: Use Convex’s built-in caching
- Monitor query performance: Use Convex dashboard
Migration Strategy
When schema changes are needed:- Add new fields as optional: Use
v.optional()for new fields - Backfill data: Write migration scripts if needed
- Deprecate old fields: Mark as optional, remove later
- Test thoroughly: Verify in development before deploying
Need Help?
- Convex Documentation: docs.convex.dev
- Schema Best Practices: docs.convex.dev/database/schemas
- Indexes Guide: docs.convex.dev/database/indexes