Skip to main content

Deployment Guide

Important Notice: This documentation is maintained as a reference for AI assistants and internal development. External contributions are not accepted.

Complete guide to deploying All My Chats to production on Google Cloud Run with Neon PostgreSQL database and GitHub Actions CI/CD.

Table of Contents​

  1. Quick Reference ⭐ Start here
  2. Deployment Architecture
  3. Prerequisites
  4. Neon Database Setup
  5. Google Cloud Setup
  6. GitHub Actions CI/CD Setup
  7. Environment Configuration
  8. Database Migration
  9. Deployment
  10. Post-Deployment Verification
  11. Monitoring & Maintenance
  12. Troubleshooting
  13. Cost Summary

Quick Reference​

One-page summary for quick deployment tasks.

Pre-Deployment Checklist (30 min)​

Required Services (Free to Start)​

ServiceLinkFree Tier
Neon Databasehttps://console.neon.tech0.5 GB, 100 CU-hrs
Google Cloud Runhttps://console.cloud.google.com2M requests/month
GitHub Actionshttps://github.comFree for public repos

Required Secrets (GitHub)​

SecretValue
GOOGLE_CREDENTIALSService account JSON key
GOOGLE_PROJECT_IDYour project ID
GOOGLE_REGIONasia-southeast1 (Singapore)
DATABASE_URLNeon connection string
BETTER_AUTH_SECRETopenssl rand -base64 32
APP_URLYour production URL
VITE_BETTER_AUTH_URLSame as APP_URL
VITE_ALLOWED_ORIGINSYour domain
GLM_API_KEYZhipu AI API key

Deployment Steps (Automated)​

  1. Push to feature/ready-to-deploy → GitHub Actions auto-deploys
  2. Wait ~5-10 minutes for build & deployment
  3. Access at: https://your-app-xxxxx.a.run.app
  4. Run migrations: DATABASE_URL="..." npm run db:migrate:run
  5. Test: signup, login, import messages

Common Issues Quick Fix​

IssueSolution
Static files 404Check server.js serves /assets/
Env vars missingCheck .dockerignore has !.env.production
Auth failsCheck BETTER_AUTH_SECRET, VITE_BETTER_AUTH_URL
Wrong credentialsUse Service Account key, not OAuth
Region mismatchVerify GOOGLE_REGION matches service region
Database failsCheck DATABASE_URL, Neon IP allowlist

Cost Estimate​

ResourceMonthly Cost
Neon DB (1.25 GB)~$0.44
Cloud Run (2M req)$0-5
Total~$0.44-5.50

Note: Neon invoices under $0.50 are NOT collected!


Deployment Architecture​

What is All My Chats?​

All My Chats is an AI-powered message analysis and categorization tool for WhatsApp conversations. It automatically categorizes and analyzes messages using multiple LLM providers (Claude, GPT-4, GLM).

Current Deployment Architecture​

┌─────────────────────────────────────────────────┐
│ GitHub Repository │
│ (whatsapp-message-AI-analysis-agent) │
└────────────────┬────────────────────────────────┘
│ Push to feature/ready-to-deploy
▼
┌─────────────────────────────────────────────────┐
│ GitHub Actions CI/CD │
│ (Build, Push to Artifact Registry) │
└────────────────┬────────────────────────────────┘
│ Deploy
▼
┌─────────────────────────────────────────────────┐
│ Google Cloud Run │
│ (All My Chats - TanStack Start) │
│ Region: asia-southeast1 (Singapore) │
└────────┬────────────────────────────────────────┘
│ Connect
▼
┌─────────────────────────────────────────────────┐
│ Neon Database │
│ (PostgreSQL 17) │
│ Region: ap-southeast-1 (Singapore) │
│ - Serverless, Auto-scaling │
│ - Branching, Time travel │
└─────────────────────────────────────────────────┘

Deployment Timeline​

  • Neon Database Setup: 10-15 minutes
  • Google Cloud Setup: 20-30 minutes
  • GitHub Actions CI/CD: 15-20 minutes
  • Environment Configuration: 10 minutes
  • First Deployment: 5-10 minutes (automated)
  • Total: ~1.5 hours for first deployment

Region Selection​

ComponentRegionWhy
Neon Databaseap-southeast-1 (Singapore)Closest to India users (~50-80ms latency)
Cloud Runasia-southeast1 (Singapore)Same region as DB, closest to India users

Prerequisites​

Required Accounts​

  1. GitHub Account - With access to your repository
  2. Google Cloud Account - Sign up at https://console.cloud.google.com
    • Free tier: $300 credit for 90 days
  3. Neon Account - Sign up at https://console.neon.tech
    • Free tier: 0.5 GB storage, 100 CU-hours compute

Required Tools​

# Check if you have these installed
git --version # Should be 2.0+
node --version # Should be 18+
npm --version # Should be 9+

Generate Required Secrets​

Open your terminal and generate the essential secret:

# Generate Better Auth secret (REQUIRED)
openssl rand -base64 32

# Save this output - you'll need it for BETTER_AUTH_SECRET

Neon Database Setup​

IMPORTANT: Complete database setup BEFORE configuring environment variables or deploying.

Step 1: Create Neon Account​

  1. Go to Neon Console
  2. Sign up with GitHub, Google, or email
  3. Verify your email address

Step 2: Create Neon Project​

  1. Click "Create a project"
  2. Configure:
FieldValueNotes
Project NameallmychatsDescriptive name
Database Nameneondb (default)Can leave as default
PostgreSQL Version17Latest stable version
Regionap-southeast-1 (Singapore)Closest to India users
Pricing PlanFree (to start)Upgrade to Launch if needed
  1. Click "Create Project"
  2. Wait for provisioning (~30 seconds)

Step 3: Get Connection String​

  1. In Neon Console, go to your project
  2. Click "Connection Details" (or SQL Editor)
  3. Copy the connection string:
postgresql://neondb_owner:[YOUR-PASSWORD]@ep-xxx.ap-southeast-1.aws.neon.tech/neondb?sslmode=require
  1. Save this securely - you'll need it for DATABASE_URL

Storage Breakdown (MVP: 100 users, 100K messages)​

ComponentSize
User data & sessions~1 MB
Messages (100K)~300 MB
Message embeddings (vectors)~600 MB ⭐ Largest
Categories, tags, metadata~30 MB
Database indexes & overhead~310 MB
Total~1.25 GB

Note: messageEmbedding (vector storage) is the largest contributor at ~600 MB.

Cost: ~$0.44/month (1.25 GB × $0.35/GB) - Likely FREE since invoices under $0.50 are not collected!


Google Cloud Setup​

Step 1: Create Google Cloud Project​

  1. Go to Google Cloud Console
  2. Click "Select a project" → "New Project"
  3. Enter project details:
FieldValue
Project Nameallmychats
Organization(leave blank for personal)
LocationNo organization
  1. Click "Create"
  2. Wait for project to be created (~30 seconds)

Step 2: Enable Required APIs​

  1. Go to APIs & Services → Library
  2. Search for and enable these APIs:
✓ Cloud Run API
✓ Cloud Build API
✓ Artifact Registry API
✓ Cloud Storage JSON API (optional, for file storage)

Step 3: Create Artifact Registry (for Docker images)​

  1. Go to Artifact Registry → Repositories
  2. Click "Create Repository"
  3. Configure:
FieldValue
Namedocker-repo
FormatDocker
Location typeRegion
Regionasia-southeast1 (Singapore)
ModeStandard
  1. Click "Create"

Step 4: Set Up Google Cloud Billing​

  1. Go to Billing → Manage
  2. Link a payment method (required for Cloud Run)
  3. Note: Google Cloud offers $300 free credit for new accounts

Step 5: Custom Domain Setup (Optional)​

Set up custom domains to replace the auto-generated xxxxx.run.app URL.

Recommended Domain Structure:

DomainPurposeWhere to Deploy
allmychats.onlineLanding pageVercel (static site)
app.allmychats.onlineFull product (frontend + API)Cloud Run

Note: You don't need a separate api. subdomain because TanStack Start serves both frontend and API routes from the same deployment.


GitHub Actions CI/CD Setup​

Step 1: Create Google Service Account​

  1. Go to IAM & Admin → Service Accounts
  2. Click "Create Service Account"
  3. Configure:
FieldValue
Service account namegithub-actions-deploy
Service account description"CI/CD deploy for Cloud Run"
  1. Click "Create and Continue"
  2. Add roles:
✓ Cloud Run Admin
✓ Cloud Run Service Agent
✓ Service Account User
✓ Artifact Registry Reader
  1. Click "Done"

Step 2: Create Service Account Key (⚠️ CRITICAL)​

⚠️ VERY IMPORTANT: You need a Service Account key for deployment, NOT an OAuth client secret!

  1. Click on the service account you just created
  2. Go to Keys tab
  3. Click "Add Key" → "Create new key"
  4. Select JSON format
  5. Click "Create"
  6. Download and save the JSON file securely

The JSON file should look like this:

{
"type": "service_account",
"project_id": "your-project-id",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...",
"client_email": "[email protected]",
"client_id": "123456789",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token"
}

⚠️ DO NOT use the OAuth client secret JSON!

Step 3: Add GitHub Secrets​

  1. Go to your GitHub repository
  2. Click Settings → Secrets and variables → Actions
  3. Click "New repository secret"
  4. Add the following secrets:

Required Secrets​

Secret NameValueNotes
GOOGLE_CREDENTIALSContent of the JSON key file (paste entire JSON)Multi-line JSON from Service Account
GOOGLE_PROJECT_IDallmychatsYour Google Cloud project ID
GOOGLE_REGIONasia-southeast1Cloud Run region (⚠️ verify matches your service)
DATABASE_URLYour Neon connection stringPostgreSQL connection string
BETTER_AUTH_SECRETYour 32-char random secretGenerate with: openssl rand -base64 32
APP_URLYour production URL (e.g., https://allmychats.online)Public URL of your app
GLM_API_KEYYour Zhipu AI API keyRequired for AI features
VITE_BETTER_AUTH_URLYour production URLSame as APP_URL
VITE_ALLOWED_ORIGINSYour domain(s), comma-separatede.g., https://allmychats.online

Step 4: Configure .dockerignore (⚠️ CRITICAL)​

⚠️ IMPORTANT: Your .dockerignore file must allow .env.production during Docker build!

Create or update .dockerignore file in your project root:

# Dependencies
node_modules

# Build outputs
.output
dist

# Environment files
.env*
!.env.example
!.env.production # <-- This line is CRITICAL for builds!

# Git
.git
.gitignore

# IDE
.vscode
.idea

# Testing
playwright-report
test-results

# Misc
*.md
*.log
temp
.DS_Store
Thumbs.db

Environment Configuration​

Environment Variables Reference​

Required Variables (Must Set)​

# Database (Neon)
DATABASE_URL=postgresql://neondb_owner:[PASSWORD]@ep-xxx.ap-southeast-1.aws.neon.tech/neondb?sslmode=require

# Authentication
BETTER_AUTH_SECRET=your-32-char-random-secret

Optional Variables (Add as Needed)​

# LLM Providers (for AI features)
ANTHROPIC_API_KEY=sk-ant-xxxxx
OPENAI_API_KEY=sk-xxxxx
GLM_API_KEY=xxxxx

# File Storage (Cloudflare R2)
R2_ACCESS_KEY_ID=xxxxx
R2_SECRET_ACCESS_KEY=xxxxx
R2_ACCOUNT_ID=xxxxx
R2_BUCKET_NAME=allmychats-uploads

# Google OAuth
GOOGLE_CLIENT_ID=xxxxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-xxxxx

# Stripe Payments
STRIPE_SECRET_KEY=sk_live_xxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxx

Database Migration​

IMPORTANT: Run migrations BEFORE deploying the application to avoid errors.

Migration Overview​

The project uses Drizzle ORM with migration files in drizzle/ directory.

Step 1: Review Migration Files​

# List all migrations
ls -la drizzle/*.sql

# Preview a migration (optional)
cat drizzle/0014_rapid_stature.sql
# Set your production DATABASE_URL
export DATABASE_URL="postgresql://user:password@host:5432/dbname"

# Run migrations
npm run db:migrate:run

# Expected output:
# ✅ Migrations completed successfully

Step 3: Verify Migration Success​

# Connect to database via Neon Console SQL Editor
# Or use psql
psql $DATABASE_URL

# Check migrations table
SELECT * FROM __drizzle_migrations ORDER BY created_at;

# List tables
\dt

Deployment​

When you push to master, main, or feature/ready-to-deploy:

# 1. Make your changes
git add .
git commit -m "Add new feature"

# 2. Push to branch
git push origin feature/ready-to-deploy

What happens automatically:

  1. ✅ GitHub Actions triggers on push
  2. ✅ Code is checked out
  3. ✅ Docker image is built
  4. ✅ Image is pushed to Google Artifact Registry
  5. ✅ Cloud Run deployment is updated
  6. ✅ New revision is deployed with zero downtime

Manual Deployment​

Option A: Trigger GitHub Actions Manually

  1. Go to GitHub repository
  2. Click Actions tab
  3. Select "Deploy to Google Cloud Run" workflow
  4. Click "Run workflow"
  5. Select branch and click "Run workflow"

Option B: Using gcloud CLI

# Deploy from local machine
gcloud run deploy allmychats \
--image asia-southeast1-docker.pkg.dev/allmychats/docker-repo/allmychats:latest \
--region asia-southeast1 \
--platform managed \
--allow-unauthenticated

Post-Deployment Verification​

Step 1: Get Your App URL​

After successful deployment, GitHub Actions will show:

Deployment URL: https://allmychats-xxxxx.a.run.app

Or find it in Google Cloud Console:

  1. Go to Cloud Run → your service
  2. Click on the service URL at the top

Step 2: Verify Deployment is Running​

  1. In Google Cloud Console → Cloud Run → your service
  2. Check status is "Running" (green checkmark)
  3. Click on Logs tab
  4. Look for:
    Server running on port 3000
    Database connected successfully

Step 3: Test Application Health​

Visit your app URL in browser:

https://allmychats-xxxxx.a.run.app

Expected:

  • ✅ Landing page loads
  • ✅ No console errors (browser DevTools)
  • ✅ "Sign Up" button visible

Step 4: Test User Registration​

  1. Click "Sign Up"
  2. Enter email and password
  3. Submit form
  4. Expected:
    • ✅ Account created successfully
    • ✅ Redirected to dashboard
    • ✅ No errors

Monitoring & Maintenance​

Neon Dashboard Monitoring​

  1. Go to Neon Console
  2. View your project dashboard
  3. Monitor:
MetricWhat to Watch
Storage UsageApproaching 1.5 GB (consider cleanup)
Active ComputeApproaching 100 CU-hours (may exceed free tier)
Request CountSpikes indicate heavy usage

Cloud Run Monitoring​

  1. Go to Cloud Run → your service → Metrics tab
  2. View:
    • Request count
    • Request latency
    • CPU/memory usage
    • Instance count

Scaling Configuration​

View current scaling:

gcloud run services describe allmychats \
--region asia-southeast1 \
--format 'value(spec.template.spec.scaling)'

Update scaling:

# Set minimum and maximum instances
gcloud run services update allmychats \
--min-instances 0 \
--max-instances 10 \
--region asia-southeast1

# Enable autoscaling
gcloud run services update allmychats \
--scaling-mode automatic \
--region asia-southeast1

Scaling Recommendations​

Traffic PatternMin InstancesMax InstancesNotes
Development01Scale to zero when idle
MVP (100 users)05Auto-scale based on traffic
Growth (1K users)110Keep 1 warm for faster response
Production (10K+)2100Multiple instances for HA

Troubleshooting​

Critical Deployment Issues (Real-World Cases)​

❌ Issue 1: Static Assets Return 404 Errors​

Symptoms:

GET https://allmychats.online/assets/main-BgDCIyLK.css net::ERR_ABORTED 404
GET https://allmychats.online/site.webmanifest 404

Root Cause: The server.js production server was not configured to serve static files (CSS, JS, manifest). It only handled API routes and SSR, leaving all static assets to return 404.

Solution: Update server.js to include static file serving functionality.


❌ Issue 2: Environment Variables Blocked by .dockerignore​

Symptoms:

Error: Environment validation failed
- DATABASE_URL: Invalid input: expected string, received undefined
- BETTER_AUTH_SECRET: Invalid input: expected string, received undefined

Root Cause: The .dockerignore file had a .env* pattern that excluded .env.production.

Solution: Add an exception for .env.production:

.env*
!.env.example
!.env.production # <-- CRITICAL: Allow this file during builds!

❌ Issue 3: Wrong Google Credentials Type (OAuth vs Service Account)​

Symptoms:

Error: provided credential is not a valid Google Service Account Key JSON

Root Cause: Using OAuth client credentials instead of Service Account credentials for deployment.

Solution:

  1. Go to IAM & Admin → Service Accounts
  2. Select your service account → Keys tab
  3. Click "Add Key" → "Create new key" → JSON
  4. Download and use this file for GOOGLE_CREDENTIALS secret

❌ Issue 4: Region Mismatch Between Deployment and Cloud Run Service​

Symptoms:

Error: Resource 'projects/allmychats/regions/asia-south1/services/allmychats' not found

Root Cause: The GitHub Actions workflow was deploying to asia-south1 (Mumbai), but the Cloud Run service was created in asia-southeast1 (Singapore).

Solution: Update GOOGLE_REGION secret in GitHub to match your existing service.


❌ Issue 5: Authentication Failures (POST Requests Return 500/403)​

Symptoms:

POST https://allmychats.online/api/auth/register 500
POST https://allmychats.online/api/auth/sign-in/social 403

Root Causes:

  1. Missing duplex option in Node.js 18+ Request
  2. Missing trustedOrigins in Better Auth config
  3. Wrong Google OAuth redirect URI

Solutions:

Fix 1: Add duplex to server.js

const webReq = new Request(url, {
method: req.method,
headers,
body: req.method !== "GET" && req.method !== "HEAD" ? req : undefined,
duplex: req.method !== "GET" && req.method !== "HEAD" ? "half" : undefined,
});

Fix 2: Configure Better Auth

export const auth = betterAuth({
secret: privateEnv.BETTER_AUTH_SECRET,
database: drizzleAdapter(database, { provider: "pg" }),
baseURL: process.env.APP_URL || process.env.VITE_BETTER_AUTH_URL || undefined,
trustedOrigins: (process.env.VITE_ALLOWED_ORIGINS || process.env.APP_URL || "")
.split(",")
.map((o) => o.trim())
.filter(Boolean),
});

Cost Summary​

Monthly Cost Breakdown (Estimated)​

ServiceMonthly CostNotes
Neon Database~$0.441.25 GB × $0.35/GB
Cloud Run~$0-52M requests free, then ~$0.40/M
Artifact Registry$00.5 GB free
Cloud Storage (optional)$05 GB free
Total~$0.44-5.50/monthDepends on traffic

Key Pricing Notes​

Neon Database:

  • Free tier: 0.5 GB storage, 100 CU-hrs compute
  • Your app uses ~1.25 GB (exceeds free tier)
  • Launch plan: $0.35/GB-month, $0.106/CU-hour
  • Invoices under $0.50 are NOT collected - you may pay nothing!

Cloud Run:

  • Free tier: 2M requests/month, 200K vCPU-seconds, 400K GB-seconds
  • Paid: $0.40 per million requests after free tier
  • Network: 10 GB egress free, then $0.12/GB

Total estimated cost: $0-5.50/month depending on traffic


Security Checklist​

Before considering deployment "complete", verify:

  • BETTER_AUTH_SECRET is strong (32+ random characters)
  • DATABASE_URL contains strong password
  • All secrets stored in GitHub Secrets (not in code)
  • .env.production NOT committed to git
  • .env.local NOT committed to git
  • Google service account has minimum required permissions
  • HTTPS enabled (automatic on Cloud Run)
  • CORS configured correctly
  • Secrets stored securely (1Password, etc.)

Last Updated: 2025-01-21 Version: Production (Google Cloud Run + Neon + GitHub Actions) For: All My Chats