This guide covers the complete deployment process for the Aqua Stark Backend API across different environments (development, staging, and production).
- Introduction
- Prerequisites
- Environment Variables
- Supabase Setup
- Dojo/Starknet Configuration
- Database Migrations
- Deployment by Environment
- Troubleshooting
- Production Considerations
This deployment guide provides step-by-step instructions for setting up and deploying the Aqua Stark Backend API. It covers:
- Environment configuration for different deployment scenarios
- External service setup (Supabase, Starknet, Dojo)
- Database migration processes
- Environment-specific deployment strategies
- Common issues and solutions
For initial setup and development, see Getting Started.
Before deploying, ensure you have:
- Node.js
>=20.10.0(exact version required) - npm or yarn package manager
- Supabase CLI (for database migrations)
- Access to:
- Supabase project (or ability to create one)
- Starknet RPC endpoint
- Cartridge authentication URL
- Dojo account (optional, for on-chain operations)
All configuration is managed through environment variables. Below is a complete reference of all available variables.
| Variable | Required | Default | Description |
|---|---|---|---|
SUPABASE_URL |
✅ Yes | - | Your Supabase project URL |
SUPABASE_KEY |
✅ Yes | - | Supabase anonymous key (anon key) |
SUPABASE_DB_URL |
❌ No | - | Database connection URL (for migrations) |
SUPABASE_ANON_KEY |
❌ No | - | Alternative anon key (if different from SUPABASE_KEY) |
SUPABASE_DB_PASSWORD |
❌ No | - | Database password (for migrations) |
STARKNET_RPC |
✅ Yes | - | Starknet RPC endpoint URL |
STARKNET_CHAIN_ID |
❌ No | SN_MAIN |
Starknet chain ID (SN_MAIN, SN_SEPOLIA, etc.) |
CARTRIDGE_AUTH_URL |
✅ Yes | - | Cartridge authentication service URL |
PORT |
❌ No | 3000 |
Server listening port |
NODE_ENV |
❌ No | development |
Environment mode (development, staging, production) |
CORS_ORIGIN |
❌ No | - | Comma-separated list of allowed origins |
CORS_CREDENTIALS |
❌ No | true |
Enable CORS credentials |
DOJO_ACCOUNT_ADDRESS |
❌ No | - | Dojo account address for on-chain operations |
DOJO_PRIVATE_KEY |
❌ No | - | Dojo account private key |
SHUTDOWN_TIMEOUT |
❌ No | 10000 |
Graceful shutdown timeout in milliseconds |
# =============================================================================
# SUPABASE CONFIGURATION
# =============================================================================
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your_anon_key_here
SUPABASE_DB_URL=postgresql://postgres:[YOUR-PASSWORD]@db.your-project.supabase.co:5432/postgres
SUPABASE_ANON_KEY=your_anon_key_here
SUPABASE_DB_PASSWORD=your_supabase_password
# =============================================================================
# STARKNET CONFIGURATION
# =============================================================================
STARKNET_RPC=https://starknet-sepolia.public.blastapi.io
STARKNET_CHAIN_ID=SN_SEPOLIA
# =============================================================================
# CARTRIDGE AUTHENTICATION
# =============================================================================
CARTRIDGE_AUTH_URL=https://cartridge.gg/auth
# =============================================================================
# SERVER CONFIGURATION
# =============================================================================
PORT=3000
NODE_ENV=development
# =============================================================================
# DOJO CONFIGURATION (Optional)
# =============================================================================
DOJO_ACCOUNT_ADDRESS=0x...
DOJO_PRIVATE_KEY=0x...
# =============================================================================
# CORS Configuration
# =============================================================================
CORS_ORIGIN=
CORS_CREDENTIALS=true
# =============================================================================
# Shutdown Configuration
# =============================================================================
SHUTDOWN_TIMEOUT=15000# =============================================================================
# SUPABASE CONFIGURATION
# =============================================================================
SUPABASE_URL=https://your-staging-project.supabase.co
SUPABASE_KEY=your_staging_anon_key
SUPABASE_DB_URL=postgresql://postgres:[PASSWORD]@db.your-staging-project.supabase.co:5432/postgres
SUPABASE_DB_PASSWORD=your_staging_password
# =============================================================================
# STARKNET CONFIGURATION
# =============================================================================
STARKNET_RPC=https://starknet-sepolia.public.blastapi.io
STARKNET_CHAIN_ID=SN_SEPOLIA
# =============================================================================
# CARTRIDGE AUTHENTICATION
# =============================================================================
CARTRIDGE_AUTH_URL=https://cartridge.gg/auth
# =============================================================================
# SERVER CONFIGURATION
# =============================================================================
PORT=4000
NODE_ENV=staging
# =============================================================================
# DOJO CONFIGURATION
# =============================================================================
DOJO_ACCOUNT_ADDRESS=0x...
DOJO_PRIVATE_KEY=0x...
# =============================================================================
# CORS Configuration
# =============================================================================
CORS_ORIGIN=https://staging.yourdomain.com
CORS_CREDENTIALS=true
# =============================================================================
# Shutdown Configuration
# =============================================================================
SHUTDOWN_TIMEOUT=10000# =============================================================================
# SUPABASE CONFIGURATION
# =============================================================================
SUPABASE_URL=https://your-production-project.supabase.co
SUPABASE_KEY=your_production_anon_key
SUPABASE_DB_URL=postgresql://postgres:[PASSWORD]@db.your-production-project.supabase.co:5432/postgres
SUPABASE_DB_PASSWORD=your_production_password
# =============================================================================
# STARKNET CONFIGURATION
# =============================================================================
STARKNET_RPC=https://starknet-mainnet.public.blastapi.io
STARKNET_CHAIN_ID=SN_MAIN
# =============================================================================
# CARTRIDGE AUTHENTICATION
# =============================================================================
CARTRIDGE_AUTH_URL=https://cartridge.gg/auth
# =============================================================================
# SERVER CONFIGURATION
# =============================================================================
PORT=4000
NODE_ENV=production
# =============================================================================
# DOJO CONFIGURATION
# =============================================================================
DOJO_ACCOUNT_ADDRESS=0x...
DOJO_PRIVATE_KEY=0x...
# =============================================================================
# CORS Configuration
# =============================================================================
CORS_ORIGIN=https://yourdomain.com,https://app.yourdomain.com
CORS_CREDENTIALS=true
# =============================================================================
# Shutdown Configuration
# =============================================================================
SHUTDOWN_TIMEOUT=10000The application validates required environment variables on startup. If a required variable is missing, the server will fail to start with a clear error message:
Error: Missing required environment variable: SUPABASE_URL
- Go to supabase.com
- Sign in or create an account
- Click "New Project"
- Fill in project details:
- Name: Your project name
- Database Password: Choose a strong password (save this for
SUPABASE_DB_PASSWORD) - Region: Select closest region
- Pricing Plan: Choose appropriate plan
After project creation, navigate to Settings > API:
- Project URL: Use for
SUPABASE_URL- Example:
https://abcdefghijklmnop.supabase.co
- Example:
- anon/public key: Use for
SUPABASE_KEY- This is the public anonymous key
- service_role key: Keep secret (not used in this API)
Storage buckets are automatically created via migrations. See Supabase Storage Setup for details.
The following buckets are created:
fish- Fish spritestanks- Tank spritesdecorations- Decoration spritesavatars- Player avatars
RLS policies are automatically enabled via migrations. All tables have appropriate policies:
players- Public read, authenticated writefish- Public read, authenticated writetanks- Public read, authenticated writedecorations- Public read, authenticated writesync_queue- Authenticated read/write
For migrations, you'll need the database connection URL:
- Go to Settings > Database
- Find "Connection string" section
- Select "URI" format
- Copy the connection string
- Replace
[YOUR-PASSWORD]with your database password - Use this for
SUPABASE_DB_URL
Example format:
postgresql://postgres:[YOUR-PASSWORD]@db.abcdefghijklmnop.supabase.co:5432/postgres
For detailed Supabase setup instructions, see Supabase Setup Guide.
Choose the appropriate RPC endpoint based on your environment:
STARKNET_RPC=https://starknet-mainnet.public.blastapi.io
STARKNET_CHAIN_ID=SN_MAINAlternative mainnet endpoints:
https://starknet-mainnet.public.blastapi.iohttps://starknet-mainnet.public.chainstack.comhttps://rpc.starknet.lava.build
STARKNET_RPC=https://starknet-sepolia.public.blastapi.io
STARKNET_CHAIN_ID=SN_SEPOLIAAlternative testnet endpoints:
https://starknet-sepolia.public.blastapi.iohttps://starknet-sepolia.public.chainstack.com
STARKNET_RPC=http://localhost:5050
STARKNET_CHAIN_ID=SN_GOERLIFor on-chain operations, configure a Dojo account:
-
Generate or Import Account:
- Use Starknet wallet (ArgentX, Braavos) or generate programmatically
- Ensure account has sufficient funds for transactions
-
Set Environment Variables:
DOJO_ACCOUNT_ADDRESS=0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
DOJO_PRIVATE_KEY=0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefSecurity Note:
- Never commit private keys to version control
- Use secrets management in production
- Rotate keys regularly
- Use different accounts for different environments
- Verify Configuration:
- If
DOJO_ACCOUNT_ADDRESSandDOJO_PRIVATE_KEYare not set, the Dojo client runs in stub mode - Stub mode logs all calls but doesn't execute real transactions
- See Dojo Stubs Documentation for details
- If
| Chain | Chain ID | Use Case |
|---|---|---|
SN_MAIN |
Mainnet | Production |
SN_SEPOLIA |
Sepolia Testnet | Development, Staging |
SN_GOERLI |
Goerli Testnet | Legacy, Local Devnet |
- Install Supabase CLI:
npm install -g supabaseOr use npx (recommended):
npx supabase --version- Login to Supabase:
npx supabase loginThis opens your browser for authentication.
- Link Your Project:
npx supabase link --project-ref your-project-refReplace your-project-ref with your Supabase project reference ID (found in project URL).
You'll be prompted for your database password.
- Apply Migrations:
npx supabase db pushThis command:
- Shows all pending migrations
- Asks for confirmation
- Executes migrations in chronological order
- Applies all SQL files from
supabase/migrations/
Migrations are located in supabase/migrations/ and follow this naming convention:
- Format:
YYYYMMDDHHMMSS_description.sql - Example:
20250108000000_create_players_table.sql
Migrations are applied in alphabetical order (by filename timestamp).
Check migration status:
npx supabase migration listSupabase doesn't support automatic rollbacks. To rollback:
- Create a new migration that reverses changes
- Or manually modify the database via Supabase Dashboard
For detailed migration instructions, see Supabase Setup Guide.
- Clone Repository:
git clone <repository-url>
cd API-Aqua-Stark- Install Dependencies:
npm install- Configure Environment:
cp .env.example .env
# Edit .env with development values- Run Migrations (if needed):
npx supabase db push- Start Development Server:
npm run devThe server starts with hot-reload on http://localhost:3000 (or your configured PORT).
- Hot-reload enabled (automatic restart on file changes)
- Debug logging enabled
- CORS allows all origins (if
CORS_ORIGINis empty) - Detailed error messages
- TypeScript source maps for debugging
- Build Application:
npm run build- Verify Build:
npm run type-check-
Set Environment Variables:
- Use staging Supabase project
- Use testnet RPC endpoints
- Configure staging CORS origins
-
Run Migrations:
npx supabase db push- Start Server:
npm start- Use separate Supabase project
- Use testnet for Starknet operations
- Configure CORS for staging domain
- Enable logging for debugging
- Use test accounts for Dojo operations
- Monitor error rates and performance
- All environment variables configured
- Database migrations applied
- Supabase storage buckets configured
- RLS policies enabled and tested
- CORS origins configured correctly
- Dojo account funded and tested
- Secrets stored securely (not in code)
- Monitoring and logging configured
- Backup strategy in place
- Build for Production:
npm run build- Verify Production Build:
# Type check
npm run type-check
# Test production build locally
NODE_ENV=production npm start-
Set Production Environment Variables:
- Use production Supabase project
- Use mainnet RPC endpoints
- Configure production CORS origins
- Set
NODE_ENV=production
-
Run Migrations:
npx supabase db push- Start Production Server:
npm start- Process Manager: Use PM2, systemd, or similar
- Reverse Proxy: Use Nginx or similar for SSL termination
- Load Balancing: For high traffic, use multiple instances
- Monitoring: Set up application monitoring (e.g., Sentry, DataDog)
- Logging: Centralized logging (e.g., ELK stack, CloudWatch)
- Health Checks: Configure health check endpoints
Create ecosystem.config.js:
module.exports = {
apps: [{
name: 'aqua-stark-api',
script: './dist/server.js',
instances: 2,
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 4000
},
error_file: './logs/err.log',
out_file: './logs/out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
merge_logs: true
}]
};Start with PM2:
pm2 start ecosystem.config.js
pm2 save
pm2 startupError: Missing required environment variable: SUPABASE_URL
Solution:
- Verify
.envfile exists in project root - Check
SUPABASE_URLis set correctly - Ensure URL format:
https://your-project.supabase.co - Restart server after changing
.env
Error: Invalid API key
Solution:
- Verify
SUPABASE_KEYmatches your project's anon key - Check key in Supabase Dashboard > Settings > API
- Ensure no extra spaces or quotes in
.envfile
Error: Failed to connect to Starknet RPC
Solution:
- Verify
STARKNET_RPCendpoint is accessible - Test endpoint with curl:
curl -X POST https://starknet-mainnet.public.blastapi.io \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"starknet_blockNumber","params":[],"id":1}'
- Try alternative RPC endpoint
- Check network connectivity
Symptoms: Server starts but uses default values
Solution:
- Ensure
.envfile is in project root (same level aspackage.json) - Check variable names match exactly (case-sensitive)
- No spaces around
=sign:KEY=valuenotKEY = value - Restart server after changes
- Verify
dotenvis installed:npm list dotenv
Error: PORT must be a number
Solution:
- Ensure
PORTis a valid integer:PORT=3000notPORT="3000"orPORT=abc
Solution:
# Unlink and re-link
npx supabase unlink
npx supabase link --project-ref your-project-refSolution:
- Check migration file timestamps are in correct order
- Verify all dependent tables are created in earlier migrations
- Review migration SQL for syntax errors
Solution:
- Verify database password is correct
- Reset password in Supabase Dashboard > Settings > Database
- Update
SUPABASE_DB_PASSWORDin.env
Error: Access-Control-Allow-Origin header missing
Solution:
- Development: Leave
CORS_ORIGINempty to allow all origins - Production: Set
CORS_ORIGINto your frontend domain:CORS_ORIGIN=https://yourdomain.com
- For multiple origins, use comma-separated list:
CORS_ORIGIN=https://yourdomain.com,https://app.yourdomain.com
- Ensure
CORS_CREDENTIALS=trueif sending cookies/auth headers
See Getting Started - CORS Issues for detailed troubleshooting.
Solution:
- This is expected if
DOJO_ACCOUNT_ADDRESSandDOJO_PRIVATE_KEYare not set - Set both variables to enable real on-chain operations
- See Dojo Stubs Documentation for details
Error: OnChainError: Failed to execute transaction
Solution:
- Verify Dojo account has sufficient funds
- Check account address and private key are correct
- Verify RPC endpoint is accessible
- Check chain ID matches network (mainnet vs testnet)
- Review transaction in Starknet explorer
Error: EADDRINUSE: address already in use :::3000
Solution:
# Find process using port
lsof -i :3000
# Kill the process
kill -9 <PID>
# Or use different port
PORT=4000 npm run devSolution:
# Check for type errors
npm run type-check
# Verify all dependencies installed
npm install
# Clear build cache
rm -rf dist
npm run buildNever commit secrets to version control:
-
Use Environment Variables: Store all secrets in environment variables
-
Use Secrets Managers:
- AWS Secrets Manager
- HashiCorp Vault
- Azure Key Vault
- Environment-specific
.envfiles (not committed)
-
Rotate Keys Regularly:
- Supabase keys
- Dojo private keys
- Database passwords
- Use Supabase anon key (not service role key) in API
- Service role key should only be used server-side for admin operations
- Implement rate limiting for public endpoints
- Use authentication middleware for protected endpoints
- Never use wildcard (
*) in production - Specify exact origins in
CORS_ORIGIN - Use HTTPS for all production origins
- Regularly review and update allowed origins
- Use connection pooling (Supabase handles this automatically)
- Index frequently queried columns
- Monitor query performance via Supabase Dashboard
- Use read replicas for high-read workloads
- Cache frequently accessed data (player data, fish metadata)
- Implement cache invalidation on updates
- Use Redis or similar for distributed caching
- Use Node.js cluster mode for multi-core utilization
- Implement request rate limiting
- Monitor memory usage and implement garbage collection tuning
- Use compression middleware for responses
Set up monitoring for:
- Server uptime and health
- Response times and latency
- Error rates and types
- Request volume and patterns
Recommended tools:
- Sentry: Error tracking
- DataDog: Application performance monitoring
- New Relic: Full-stack observability
- Grafana + Prometheus: Self-hosted monitoring
- Use structured logging (JSON format)
- Log levels:
error,warn,info,debug - Include request IDs for tracing
- Rotate logs to prevent disk space issues
- Send critical logs to centralized system
The API includes a health check endpoint:
GET /api/health
Configure your load balancer or monitoring system to check this endpoint regularly.
Supabase provides automatic backups:
- Daily backups retained for 7 days
- Point-in-time recovery available
- Manual backup via Supabase Dashboard
- Store critical state in database (not memory)
- Implement graceful shutdown to prevent data loss
- Use transaction logs for recovery
- Test recovery procedures regularly
- Document Recovery Procedures: Step-by-step recovery guide
- Regular Backups: Automated daily backups
- Test Restores: Periodically test backup restoration
- Multi-Region: Consider multi-region deployment for high availability
- Incident Response: Define roles and procedures for incidents
- Run multiple server instances behind load balancer
- Use stateless application design (all state in database)
- Implement session stickiness if needed (via load balancer)
- Increase server resources (CPU, memory)
- Optimize database queries
- Use database read replicas
- Supabase handles automatic scaling
- Monitor connection pool usage
- Consider read replicas for high-read workloads
- Implement database query optimization
- Always use HTTPS in production
- Configure SSL certificates (Let's Encrypt, Cloudflare, etc.)
- Use reverse proxy (Nginx, Caddy) for SSL termination
- Enable HSTS headers
- Regularly update SSL certificates
- Blue-Green Deployment: Run two environments, switch traffic
- Rolling Updates: Update instances gradually
- Canary Releases: Deploy to subset of traffic first
- Schedule maintenance during low-traffic periods
- Notify users in advance
- Have rollback plan ready
- Test updates in staging first
- Use semantic versioning
- Tag releases in Git
- Document breaking changes
- Maintain changelog
- Getting Started Guide - Initial setup and development
- Supabase Setup Guide - Detailed Supabase configuration
- Supabase Storage Setup - Storage bucket configuration
- Dojo Stubs Documentation - Dojo client configuration
- Architecture Documentation - System architecture overview
- Error Handling Guide - Error management system
If you encounter issues not covered in this guide:
- Check the Troubleshooting section
- Review other documentation in
/docs - Check application logs for detailed error messages
- Verify all environment variables are set correctly
- Test with minimal configuration to isolate issues