Overview
Convex is a serverless database that provides:- Real-time reactive queries
- Type-safe database operations
- Automatic indexing and optimization
- Built-in authentication integration
- Serverless functions for business logic
Prerequisites
Before deploying the database:- Convex Account: Sign up at dashboard.convex.dev
- Bun Installed: ZapDev uses Bun as the package manager
- Environment Variables: Configure
NEXT_PUBLIC_CONVEX_URL(see Environment Variables)
Deployment
Initial Deployment
Deploy your Convex schema to production:Development Mode
For local development, run Convex in dev mode:- Live schema updates
- Development dashboard at
http://localhost:3000/_convex - Real-time function logs
- Database explorer
Database Schema
ZapDev’s database consists of 15 tables defined inconvex/schema.ts.
Core Tables
projects
Stores user projects and their configurations. Fields:name(string) - Project nameuserId(string) - Owner’s user IDframework(enum) - Framework choice:NEXTJS,ANGULAR,REACT,VUE,SVELTEmodelPreference(string, optional) - Preferred AI modelcreatedAt(number, optional) - Unix timestampupdatedAt(number, optional) - Unix timestamp
by_userId- Find projects by userby_userId_createdAt- User projects ordered by creation date
messages
Stores conversation messages between users and AI agents. Fields:content(string) - Message textrole(enum) -USERorASSISTANTtype(enum) -RESULT,ERROR, orSTREAMINGstatus(enum) -PENDING,STREAMING, orCOMPLETEprojectId(id) - Reference to parent projectcreatedAt(number, optional) - Unix timestampupdatedAt(number, optional) - Unix timestamp
by_projectId- Messages for a projectby_projectId_createdAt- Project messages ordered by time
fragments
Stores generated code fragments and sandbox metadata. Fields:messageId(id) - Reference to parent messagesandboxUrl(string) - E2B sandbox URLtitle(string) - Fragment titlefiles(any) - Generated file contentsmetadata(any, optional) - Additional metadataframework(enum) - Framework usedcreatedAt(number, optional) - Unix timestampupdatedAt(number, optional) - Unix timestamp
by_messageId- Fragments for a message
Usage & Rate Limiting
usage
Tracks user credit consumption. Fields:userId(string) - User IDpoints(number) - Credits consumedexpire(number, optional) - Expiration timestampplanType(enum, optional) -free,pro, orunlimited
by_userId- User’s usage recordsby_expire- For cleanup of expired records
- Free tier: 5 generations/day
- Pro tier: 100 generations/day
- Unlimited tier: No limits
rateLimits
Generic rate limiting for API endpoints. Fields:key(string) - Rate limit identifiercount(number) - Request count in windowwindowStart(number) - Window start timestamplimit(number) - Maximum requests allowedwindowMs(number) - Window duration in milliseconds
by_key- Find limit by keyby_windowStart- Cleanup old windows
Subscriptions & Billing
subscriptions
Stores Polar.sh subscription data. Fields:userId(string) - User IDpolarSubscriptionId(string) - Polar.sh subscription IDcustomerId(string) - Polar.sh customer IDproductId(string) - Product IDpriceId(string) - Price IDstatus(enum) -active,past_due,canceled,unpaid,trialinginterval(enum) -monthlyoryearlycurrentPeriodStart(number) - Period start timestampcurrentPeriodEnd(number) - Period end timestampcancelAtPeriodEnd(boolean) - Auto-cancel flagcanceledAt(number, optional) - Cancellation timestamptrialStart(number, optional) - Trial starttrialEnd(number, optional) - Trial endmetadata(any, optional) - Additional datacreatedAt(number) - Creation timestampupdatedAt(number) - Last update timestamp
by_userId- User’s subscriptionsby_polarSubscriptionId- Find by Polar IDby_customerId- Find by customerby_status- Filter by status
polarCustomers
Maps users to Polar.sh customers. Fields:userId(string) - User IDpolarCustomerId(string) - Polar.sh customer IDcreatedAt(number) - Creation timestampupdatedAt(number) - Last update timestamp
by_userId- Find by userby_polarCustomerId- Find by Polar customer ID
Imports & OAuth
imports
Tracks Figma and GitHub imports. Fields:userId(string) - User IDprojectId(id) - Target projectmessageId(id, optional) - Associated messagesource(enum) -FIGMAorGITHUBsourceId(string) - External resource IDsourceName(string) - Resource namesourceUrl(string) - Resource URLstatus(enum) -PENDING,PROCESSING,COMPLETE,FAILEDmetadata(any, optional) - Import metadataerror(string, optional) - Error messagecreatedAt(number) - Creation timestampupdatedAt(number) - Last update timestamp
by_userId- User’s importsby_projectId- Project importsby_status- Filter by status
oauthConnections
Stores OAuth tokens for external services. Fields:userId(string) - User IDprovider(enum) -figmaorgithubaccessToken(string) - Encrypted access tokenrefreshToken(string, optional) - Encrypted refresh tokenexpiresAt(number, optional) - Token expirationscope(string) - OAuth scopesmetadata(any, optional) - Provider-specific datacreatedAt(number) - Creation timestampupdatedAt(number) - Last update timestamp
by_userId- User’s connectionsby_userId_provider- Specific provider connection
Webhooks & Events
webhookEvents
Tracks webhook events from external services (Polar.sh). Fields:eventId(string) - External event IDeventType(string) - Event type (e.g.,subscription.created)status(enum) -received,processed,failed,retryingpayload(any) - Event payloaderror(string, optional) - Error messageprocessedAt(number, optional) - Processing timestampretryCount(number) - Retry attemptscreatedAt(number) - Receipt timestamp
by_eventId- Find by event ID (deduplication)by_status- Filter by statusby_eventType- Filter by typeby_createdAt- Ordered events
pendingSubscriptions
Temporary storage for subscriptions awaiting user creation. Fields:polarSubscriptionId(string) - Polar subscription IDcustomerId(string) - Polar customer IDeventData(any) - Subscription datastatus(enum) -pending,resolved,failedresolvedUserId(string, optional) - Linked user IDerror(string, optional) - Error messagecreatedAt(number) - Creation timestampresolvedAt(number, optional) - Resolution timestamp
by_polarSubscriptionId- Find by subscriptionby_customerId- Find by customerby_status- Filter by status
Attachments & Metadata
attachments
Stores file attachments for messages. Fields:type(enum) -IMAGE,FIGMA_FILE,GITHUB_REPOurl(string) - File URLwidth(number, optional) - Image widthheight(number, optional) - Image heightsize(number) - File size in bytesmessageId(id) - Parent messageimportId(id, optional) - Related importsourceMetadata(any, optional) - Source-specific datacreatedAt(number, optional) - Creation timestampupdatedAt(number, optional) - Last update timestamp
by_messageId- Attachments for a message
fragmentDrafts
Temporary storage for in-progress code fragments. Fields:projectId(id) - Parent projectfiles(any) - Draft file contentsframework(enum) - Framework typecreatedAt(number, optional) - Creation timestampupdatedAt(number, optional) - Last update timestamp
by_projectId- Drafts for a project
Agent Runs
agentRuns
Tracks AI agent execution status. Fields:projectId(id) - Target projectvalue(string) - User input/promptmodel(string, optional) - AI model usedframework(string, optional) - Framework choicestatus(enum) -PENDING,RUNNING,COMPLETED,FAILEDrunSource(enum) -WEBCONTAINERorINNGESTclaimedBy(string, optional) - Execution worker IDmessageId(id, optional) - Result messagefragmentId(id, optional) - Result fragmenterror(string, optional) - Error messagecreatedAt(number) - Creation timestampupdatedAt(number) - Last update timestampcompletedAt(number, optional) - Completion timestamp
by_projectId- Runs for a projectby_projectId_status- Project runs by statusby_status- All runs by statusby_projectId_createdAt- Project runs ordered by time
Database Operations
Common Queries
Get User’s Projects
Get Project Messages
Mutations
Create Project
Update Subscription Status
Schema Migrations
Convex automatically handles schema migrations.Adding a New Field
- Update
convex/schema.ts:
- Deploy the change:
- Add the new field to the schema
- Preserve existing data
- Make the field available immediately
Adding an Index
- Update schema with new index:
- Deploy:
Performance Optimization
Best Practices
Bad:Pagination
For large result sets, use pagination:Caching
Convex queries are reactive and automatically cached. To optimize:- Split queries - Separate frequently changing data from static data
- Use specific indexes - More specific indexes = better performance
- Limit result size - Use pagination for large datasets
Monitoring
Convex Dashboard
Monitor your database at dashboard.convex.dev:- Data Tab - View and edit table data
- Functions Tab - Monitor query/mutation execution
- Logs Tab - View function logs and errors
- Usage Tab - Track database operations and bandwidth
Key Metrics
- Database reads/writes - Track operation volume
- Function duration - Identify slow queries
- Error rate - Monitor failed operations
- Bandwidth - Track data transfer
Troubleshooting
”Schema validation failed”
Cause: Data doesn’t match schema definition Solution: Check that all required fields are provided and types match:“Index not found”
Cause: Query references non-existent index Solution: Add the index toconvex/schema.ts and deploy:
Slow Queries
Cause: Missing indexes or inefficient queries Solution:- Check Convex Dashboard → Functions → Slow queries
- Add indexes for frequently queried fields
- Use pagination for large result sets
- Avoid
.filter()- use.withIndex()instead
Backup & Recovery
Convex automatically backs up your data:- Point-in-time recovery - Available for up to 30 days
- Snapshot exports - Download data as JSON
- Automatic replication - Multi-region redundancy
- Go to Convex Dashboard → Settings → Export
- Select tables to export
- Download JSON files
Next Steps
Deploy Application
Complete your deployment with Vercel
Environment Variables
Review all required configuration