Database Schema

Staque IO uses PostgreSQL to store user data, conversations, deployed resources, and model configurations.

Core Tables

users

Stores user account information and authentication credentials.

ColumnTypeDescription
idUUIDPrimary key
usernameVARCHAR(255)Unique username
emailVARCHAR(255)Unique email address
password_hashTEXTBcrypt password hash
nameVARCHAR(255)Full name
organizationVARCHAR(255)Organization name
aws_regionVARCHAR(50)Default AWS region
roleVARCHAR(50)User role (super_admin, admin, user)
is_activeBOOLEANAccount status
created_atTIMESTAMPAccount creation time
updated_atTIMESTAMPLast update time
last_loginTIMESTAMPLast login timestamp

conversations

Top-level container for chat conversations.

ColumnTypeDescription
idUUIDPrimary key
user_idUUIDForeign key to users
titleVARCHAR(255)Conversation title
use_caseVARCHAR(255)Use case category
statusVARCHAR(50)Conversation status
created_atTIMESTAMPCreation time
updated_atTIMESTAMPLast update time

conversation_threads

Individual chat threads with message history and usage tracking.

ColumnTypeDescription
idUUIDPrimary key
conversation_idUUIDForeign key to conversations
user_idUUIDForeign key to users
thread_dataJSONBMessage history and metadata
model_idVARCHAR(255)AI model identifier
tokens_input_totalINTEGERTotal input tokens
tokens_output_totalINTEGERTotal output tokens
tokens_totalINTEGERTotal tokens used
requests_countINTEGERNumber of requests
cost_total_usdDECIMAL(10,6)Total cost in USD
last_usage_atTIMESTAMPLast activity timestamp
created_atTIMESTAMPThread creation time
updated_atTIMESTAMPLast update time

deployed_resources

Tracks deployed AI model resources across different platforms.

ColumnTypeDescription
idUUIDPrimary key
conversation_idUUIDForeign key to conversations
user_idUUIDForeign key to users
resource_nameVARCHAR(255)Resource display name
resource_typeVARCHAR(50)bedrock, sagemaker, nvidia-nim
aws_resource_idVARCHAR(255)AWS resource identifier
instance_typeVARCHAR(100)Instance type (for SageMaker)
regionVARCHAR(50)AWS region
statusVARCHAR(50)Resource status
endpoint_urlTEXTAPI endpoint URL
estimated_hourly_costDECIMAL(10,4)Hourly cost estimate
deployment_configJSONBDeployment configuration
is_activeBOOLEANActive status

model_configurations

Stores model-specific configurations including system prompts and pricing.

ColumnTypeDescription
idUUIDPrimary key (matches resource ID)
model_idVARCHAR(255)Unique model identifier
system_promptTEXTSystem prompt for the model
per_1k_input_tokens_usdDECIMAL(10,6)Cost per 1K input tokens
per_1k_output_tokens_usdDECIMAL(10,6)Cost per 1K output tokens
updated_byUUIDForeign key to users
created_atTIMESTAMPCreation timestamp
updated_atTIMESTAMPLast update timestamp

chat_messages (Legacy)

Legacy table for storing individual chat messages. Being phased out in favor of conversation_threads.

Relationships

users
  ├─ conversations (one-to-many)
  │   ├─ deployed_resources (one-to-many)
  │   └─ conversation_threads (one-to-many)
  │       └─ thread_data.messages (embedded array)
  └─ chat_messages (one-to-many, legacy)

deployed_resources
  └─ model_configurations (one-to-one via id)

Indexes

Key indexes for query performance:

  • users.username - Unique index for login
  • users.email - Unique index for email lookup
  • conversations.user_id - For user's conversation list
  • conversation_threads.conversation_id - For thread lookup
  • deployed_resources.aws_resource_id - For resource lookup
  • model_configurations.model_id - Unique index for model config

Sample Queries

Get User Conversations with Resources

SELECT 
  c.*,
  json_agg(dr.*) as deployed_resources
FROM conversations c
LEFT JOIN deployed_resources dr ON dr.conversation_id = c.id
WHERE c.user_id = $1
GROUP BY c.id
ORDER BY c.updated_at DESC;

Get Thread with Usage Statistics

SELECT 
  id,
  thread_data,
  model_id,
  tokens_input_total,
  tokens_output_total,
  tokens_total,
  requests_count,
  cost_total_usd,
  last_usage_at
FROM conversation_threads
WHERE conversation_id = $1
ORDER BY created_at DESC;

Calculate Monthly Usage by User

SELECT 
  u.username,
  SUM(ct.tokens_total) as total_tokens,
  SUM(ct.cost_total_usd) as total_cost,
  SUM(ct.requests_count) as total_requests
FROM users u
JOIN conversations c ON c.user_id = u.id
JOIN conversation_threads ct ON ct.conversation_id = c.id
WHERE ct.updated_at >= date_trunc('month', now())
GROUP BY u.id, u.username
ORDER BY total_cost DESC;

Migration Scripts

Initial database setup:

-- See database/schema.sql for complete schema
-- Run migrations:
psql -U postgres -d staque_io -f database/schema.sql

Backup and Maintenance

Regular Backups

# Full database backup
pg_dump -U postgres -d staque_io > backup_$(date +%Y%m%d).sql

# Compressed backup
pg_dump -U postgres -d staque_io | gzip > backup_$(date +%Y%m%d).sql.gz

Restore from Backup

# Restore from SQL file
psql -U postgres -d staque_io < backup_20240101.sql

# Restore from compressed backup
gunzip -c backup_20240101.sql.gz | psql -U postgres -d staque_io

💡 Best Practices

  • Enable connection pooling for better performance
  • Use prepared statements to prevent SQL injection
  • Regularly backup the database
  • Monitor query performance and add indexes as needed
  • Archive old conversation threads to maintain performance
  • Set up automated backup schedules