Last updated: Jul 25, 2025, 10:08 AM UTC

Production Deployment Guide - Unified API

Generated: 2025-07-24 11:12 UTC
Status: Ready for Deployment - Building on Existing v1 Infrastructure
Verified:

Overview

This guide leverages the existing v1 deployment infrastructure to deploy the unified API to production. The good news: most infrastructure is already in place from the v1 deployment, including GCP project, service accounts, Firestore, and Stripe integration.

What's Already Available (From v1 Deployment)

GCP Project - Ready to Use

  • Project ID: convert-to-markdown-us-east4
  • Region: us-east4
  • Billing: Active and configured
  • APIs: Already enabled (Cloud Functions, Firestore, etc.)

Service Account - Ready

  • File: deploy-gcp/keys/gmail-service-account.json
  • Permissions: Configured for Firestore and Cloud Functions
  • Status: Production ready

Firestore Database - Fully Configured

Collections already created:

  • api_keys - API key management
  • users - User accounts and plans
  • usage_stats - Monthly usage tracking
  • usage_records - Detailed usage logs
  • usage_daily_stats - Daily aggregated statistics

Authentication System - Ready

  • API key validation middleware
  • Usage quota checking
  • Plan management (free/pro)

Stripe Integration - Live Configuration

  • Live keys configured
  • Products and pricing set up
  • Ready for production payments

Quick Production Deployment

Since most infrastructure exists, deployment is simplified:

Step 1: Set Environment Variables

The unified API needs to know about the existing service account:

cd unified-api

# Create .env file (if not exists)
cat > .env << EOF
GOOGLE_APPLICATION_CREDENTIALS=../deploy-gcp/keys/gmail-service-account.json
NODE_ENV=production
PROJECT_ID=convert-to-markdown-us-east4
REGION=us-east4
EOF

Step 2: Verify Firestore Collections

Good news! The collections already exist and match the middleware:

  • api_keys - Already configured in auth middleware
  • usage_stats - Already configured for quota checking
  • users - For user management
  • usage_records - For detailed tracking

No collection name fixes needed - the existing setup is consistent!

Production Deployment Steps

Step 3: Deploy the Unified API (Using Existing Infrastructure)

cd deploy-gcp

# Verify configuration is ready
echo "Project: $(grep PROJECT_ID deployment.env)"
echo "Region: $(grep REGION deployment.env)"

# Deploy using existing service account and Firestore
./06-deploy-unified-api.sh

Expected output:

✅ Unified API deployed successfully!
API URL: https://convert-api-qpg64cvnga-uk.a.run.app

Step 4: Create Production API Key (Using Existing Firestore)

The api_keys collection already exists! Let's add your production key:

Option A: Use Existing Setup Script (Recommended)

cd unified-api

# The setup script may already have created test data
# Check if there's already data in Firestore
node -e "
const { Firestore } = require('@google-cloud/firestore');
const db = new Firestore();
db.collection('api_keys').limit(5).get().then(snapshot => {
  console.log('Existing API keys:', snapshot.size);
  snapshot.forEach(doc => console.log('- Key ID:', doc.id.substring(0, 20) + '...'));
});
"

Option B: Add New Production Key

If you need a fresh production key:

# Generate new key
node scripts/create-api-key.js lindsay@knowcode.tech pro

# Then add to existing api_keys collection via Firebase Console

Step 5: Verify Existing Usage Tracking

Check if usage tracking is already set up:

cd unified-api
node -e "
const { Firestore } = require('@google-cloud/firestore');
const db = new Firestore();
db.collection('usage_stats').limit(3).get().then(snapshot => {
  console.log('Usage stats documents:', snapshot.size);
  if (snapshot.size === 0) {
    console.log('Need to initialize usage tracking');
  } else {
    console.log('Usage tracking already configured');
  }
});
"

Step 6: Test Production API

# 1. Health check (no auth)
curl https://convert-api-qpg64cvnga-uk.a.run.app/v1/health

# 2. List endpoints (no auth)
curl https://convert-api-qpg64cvnga-uk.a.run.app/v1

# 3. Test with existing API key (if you have one from v1)
# First, let's find an existing key:
cd unified-api
node -e "
const { Firestore } = require('@google-cloud/firestore');
const db = new Firestore();
db.collection('api_keys').where('email', '==', 'lindsay@knowcode.tech').limit(1).get()
.then(snapshot => {
  if (!snapshot.empty) {
    console.log('Found existing API key:', snapshot.docs[0].id);
  } else {
    console.log('No existing API key found - create one');
  }
});
"

# 4. Test conversion (replace YOUR_API_KEY with actual key)
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "file=@../test-documents/SaaS_AssessmentQuestionnaire.pdf" \
  https://convert-api-qpg64cvnga-uk.a.run.app/v1/convert/pdf-to-markdown

# 5. Run automated tests (if you have existing API key)
cd ../deploy-gcp
TEST_API_KEY="YOUR_API_KEY" ./07-test-unified-api.sh

Step 7: Configure Domain Mapping (If Not Already Done)

Check if domain is already mapped:

gcloud run domain-mappings list --region=us-east4

If not mapped yet:

# Get the Cloud Run service name
SERVICE_NAME=$(gcloud run services list --region=us-east4 \
  --filter="metadata.labels.function_name=convert-api" \
  --format="value(name)")

# Create domain mapping (may already exist from v1)
gcloud run domain-mappings create \
  --service=$SERVICE_NAME \
  --domain=convert-to-markdown.knowcode.tech \
  --region=us-east4

Step 8: Verify SSL Certificate (Should Already Work)

The domain should already be configured from v1:

# Check SSL (should already work)
curl -I https://convert-to-markdown.knowcode.tech/v1/health

# Expected: HTTP/2 200 with SSL headers

Post-Deployment Tasks

1. Clean Up Old Functions (If Any Exist)

Check what functions currently exist:

gcloud functions list --region=us-east4

# You should see convert-api and possibly some old individual functions
# Clean up only if old functions exist and unified API is working

If old functions exist and need cleanup:

cd deploy-gcp
./cleanup-old-functions.sh

2. Leverage Existing Monitoring

The v1 deployment likely already has monitoring set up:

Check Existing Monitoring

# View current functions and their status
gcloud functions list --region=us-east4

# Check logs for the unified API
gcloud functions logs read convert-api --region=us-east4 --limit=20

Cloud Console (Already Configured)

  1. Go to Cloud Console > Cloud Functions
  2. The project already has monitoring dashboards
  3. Alerts may already be configured from v1

3. Update Documentation (Minimal Changes Needed)

Since you're building on existing infrastructure:

  • API documentation may already exist
  • Domain should already be working
  • Most integration guides can remain the same

Production Testing Protocol

Functional Tests

# Test each converter
endpoints=(
  "excel-to-json"
  "excel-to-markdown"
  "pdf-to-markdown"
  "word-to-html"
  "word-to-markdown"
)

for endpoint in "${endpoints[@]}"; do
  echo "Testing $endpoint..."
  # Add appropriate test file for each type
done

Performance Tests

Monitor these metrics:

  • Response time: Should be < 3s for most files
  • Memory usage: Should stay under 1GB
  • Cold start time: Expected 1-3s

Error Handling Tests

# No API key
curl -X POST -F "file=@test.pdf" https://your-api/v1/convert/pdf-to-markdown

# Invalid file type
curl -X POST -H "X-API-Key: your-key" -F "file=@test.txt" \
  https://your-api/v1/convert/pdf-to-markdown

# File too large (>10MB)
curl -X POST -H "X-API-Key: your-key" -F "file=@large-file.pdf" \
  https://your-api/v1/convert/pdf-to-markdown

Troubleshooting

Issue: "Cannot connect to Firestore"

Unlikely - Firestore is already working from v1 deployment
Solution:

  • Verify .env file points to correct service account
  • Check: ../deploy-gcp/keys/gmail-service-account.json exists

Issue: "API key not found"

Check existing setup:

  • Collection api_keys should already exist
  • Use script to find existing keys: see Step 6 above
  • Service account already has correct permissions

Issue: "Container failed to start"

Should not occur - the unified API uses Busboy and has been tested
If it happens:

  • Check Cloud Build logs in GCP Console
  • Verify all dependencies are in package.json

Issue: "Domain already mapped to another service"

Expected - Domain may be mapped to v1 functions
Solution:

  • List current mappings: gcloud run domain-mappings list --region=us-east4
  • Update existing mapping to point to convert-api service

Rollback Plan

If issues occur:

# 1. Get previous version
gcloud functions describe convert-api --region=us-east4 \
  --format="value(serviceConfig.revision)"

# 2. Rollback to previous version
gcloud run services update-traffic convert-api \
  --region=us-east4 \
  --to-revisions=PREVIOUS_REVISION=100

# 3. Or redeploy old functions
cd deploy-gcp
./06-deploy-public-functions.sh  # Old script

Success Criteria

Production is considered successful when:

  • Health endpoint returns 200 (Should work immediately)
  • All converters work with existing API key
  • Error rate < 1% (Tested in development)
  • Response time < 3s for 95% of requests (Tested locally)
  • Custom domain with SSL working (Should already work from v1)
  • Usage tracking recording in Firestore (Already configured)
  • Old functions removed (if any exist)
  • Stripe integration still working (Already configured)

Next Steps After Production

  1. Quick Verification (15 minutes)

    • Test health endpoint
    • Test one converter with existing API key
    • Check Firestore usage recording
  2. Monitor Performance (24 hours)

    • Existing monitoring should show unified API metrics
    • Check error rates in Cloud Console
  3. Optional Enhancements

    • PowerPoint converter (when needed)
    • API key self-service UI
    • Enhanced analytics dashboard

Deployment Time Estimate

Since infrastructure exists: 15-30 minutes total

  • Deploy function: 5-10 minutes
  • Test endpoints: 5 minutes
  • Verify existing integrations: 5-10 minutes
  • Domain should already work (no wait time)

This is significantly faster than starting from scratch thanks to the existing v1 infrastructure!