Skip to main content

Database Schema Overview

Zzyra uses PostgreSQL with Prisma ORM for data persistence. The schema is designed to support all platform features including user management, workflow execution, block system, and billing.

Schema Architecture

User Management

User
Profile
Team
TeamMember

Workflow System

Workflow
WorkflowExecution
NodeExecution
ExecutionLog

Block System

BlockLibrary
CustomBlock
BlockVersion

Billing & Notifications

Subscription
PricingTier
Notification
NotificationPreference

Core Models

User Management

model User {
  id                String   @id @default(cuid())
  email             String   @unique
  magicDid          String?  @unique
  walletAddress     String?  @unique
  isActive          Boolean  @default(true)
  emailVerified     Boolean  @default(false)
  createdAt         DateTime @default(now())
  updatedAt         DateTime @updatedAt

// Relations
profile Profile?
teams TeamMember[]
workflows Workflow[]
executions WorkflowExecution[]
subscriptions Subscription[]
notifications Notification[]
notificationPrefs NotificationPreference[]

@@map("users")
}

Workflow System

model Workflow {
  id          String   @id @default(cuid())
  name        String
  description String?
  version     Int      @default(1)
  isActive    Boolean  @default(true)
  isPublic    Boolean  @default(false)
  config      Json     // Workflow configuration
  nodes       Json     // Workflow nodes and connections
  userId      String
  teamId      String?
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

// Relations
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
team Team? @relation(fields: [teamId], references: [id])
executions WorkflowExecution[]

@@map("workflows")
}

Block System

model BlockLibrary {
  id          String   @id @default(cuid())
  name        String
  description String?
  category    String
  version     String   @default("1.0.0")
  config      Json     // Block configuration schema
  code        String?  // Block implementation code
  isActive    Boolean  @default(true)
  isBuiltin   Boolean  @default(false)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

// Relations
versions BlockVersion[]

@@map("block_library")
}

Billing & Notifications

model Subscription {
  id            String   @id @default(cuid())
  userId        String
  tierId        String
  status        SubscriptionStatus @default(ACTIVE)
  currentPeriodStart DateTime
  currentPeriodEnd   DateTime
  cancelAtPeriodEnd Boolean @default(false)
  canceledAt    DateTime?
  endedAt       DateTime?
  trialStart    DateTime?
  trialEnd      DateTime?
  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt

// Relations
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
tier PricingTier @relation(fields: [tierId], references: [id])

@@map("subscriptions")
}

Enums and Types

πŸ“‹ Database Enums

ExecutionStatus

enum ExecutionStatus {
  PENDING
  RUNNING
  COMPLETED
  FAILED
  CANCELLED
  TIMEOUT
}

SubscriptionStatus

enum SubscriptionStatus {
  ACTIVE
  CANCELED
  PAST_DUE
  UNPAID
  TRIAL
}

BillingInterval

enum BillingInterval {
  MONTHLY
  YEARLY
  ONE_TIME
}

NotificationType

enum NotificationType {
  WORKFLOW_COMPLETED
  WORKFLOW_FAILED
  SYSTEM_ALERT
  BILLING_REMINDER
  SECURITY_ALERT
}

Database Relationships

πŸ”— Key Relationships

User Management

User1:1Profile
User1:NTeamMember
Team1:NTeamMember

Workflow System

User1:NWorkflow
Workflow1:NWorkflowExecution
WorkflowExecution1:NNodeExecution

Block System

User1:NCustomBlock
BlockLibrary1:NBlockVersion

Billing System

User1:NSubscription
PricingTier1:NSubscription

Database Operations

πŸ—„οΈ Common Operations

// Create user with profile
const user = await prisma.user.create({
  data: {
    email: '[email protected]',
    magicDid: 'did:magic:...',
    profile: {
      create: {
        firstName: 'John',
        lastName: 'Doe'
      }
    }
  },
  include: {
    profile: true
  }
});

// Get user with all relations
const userWithData = await prisma.user.findUnique({
where: { id: userId },
include: {
profile: true,
teams: {
include: {
team: true
}
},
workflows: true,
subscriptions: {
include: {
tier: true
}
}
}
});

Migration Management

πŸ”„ Database Migrations

Create Migration

# Create new migration
cd packages/database
pnpm prisma migrate dev --name add_user_profile

# Apply migrations

pnpm prisma migrate deploy

# Reset database

pnpm prisma migrate reset

Schema Management

# Generate Prisma client
pnpm prisma generate

# Push schema changes
pnpm prisma db push

# Pull schema from database
pnpm prisma db pull

Best Practices

  • Always create migrations for schema changes
  • Test migrations on development database first
  • Use descriptive migration names
  • Backup production database before migrations
  • Review generated SQL before applying

Performance Optimization

⚑ Performance Tips

  • users(email) - Unique index for email lookups
  • users(magicDid) - Unique index for Magic authentication
  • workflows(userId, isActive) - Composite index for user workflows
  • workflow_executions(workflowId, status) - Composite index for execution queries
  • node_executions(executionId, status) - Composite index for node execution queries
  • Use select to limit returned fields
  • Use include for related data instead of separate queries
  • Implement pagination for large result sets
  • Use database-level filtering instead of application filtering
  • Consider read replicas for analytics queries
  • Configure appropriate connection pool size
  • Monitor connection usage and performance
  • Use connection pooling in production
  • Implement connection retry logic
  • Monitor query performance with slow query logs

Next Steps

The database schema is designed to be scalable and maintainable. Always use migrations for schema changes and test thoroughly before applying to production. For complex queries or performance optimization, consider using database views or stored procedures.