ATOM Documentation

← Back to App

Single-App Architecture - CRITICAL DEPLOYMENT GUIDE

**Date Unified:** 2026-02-24

**Commit:** 50958d329ec7329b68470cf6288ee92b3e5f2788

**Author:** Rushi Parikh

---

⚠️ CRITICAL: WE ARE A SINGLE-APP DEPLOYMENT

**atom-saas-api.fly.dev DOES NOT EXIST AND MUST NEVER BE REFERENCED**

---

Why This Change Was Made

Root Cause: HTTP 431 Errors

**Problem:** Requests to atom-saas-api.fly.dev were failing with HTTP 431 (Request Header Fields Too Large)

**Technical Root Cause:**

  • Each proxy hop adds a Via header
  • Fly.io proxy architecture accumulated 50+ hops
  • Request headers exceeded the 64KB limit
  • Example header chain: via: 1.1 fly.io, 1.1 fly.io, 1.1 fly.io... (50+ times)

**Why This Happened:**

  • Dual-app setup: atom-saas (Next.js) → atom-saas-api (Python FastAPI)
  • Every API request went through multiple proxy layers
  • Fly.io's internal routing added hops with each proxy

Solution: Unified Single-App Architecture

**What Changed:**

  1. **Single Container**: Both Next.js (port 3000) and Python FastAPI (port 8000) run in SAME container
  2. **Internal Communication**: PYTHON_BACKEND_URL = "http://localhost:8000" (localhost, not external URL)
  3. **Removed**: atom-saas-api.fly.dev app completely deleted
  4. **Memory Upgrade**: 1GB → 2GB per process to handle both services

**Process Management:**

  • supervisord manages both processes
  • docker-entrypoint.sh starts both when ROLE=web
  • Configuration in supervisord.conf

---

DEPLOYMENT CONFIGURATION

fly.toml

[build.args]
  PYTHON_BACKEND_URL = "http://localhost:8000"  # ✅ CORRECT

[env]
  PYTHON_BACKEND_URL = "http://localhost:8000"  # ✅ CORRECT
  ROLE = 'web'  # Starts both Next.js + Python

[processes]
  app = "docker-entrypoint.sh"  # ✅ CORRECT (Triggers entrypoint path)
  # ❌ WRONG: app = "web" (Fails with "No such file or directory")

.dockerignore (🔴 CRITICAL for context size)

**Problem:** Including .next/cache or **/venv/ can bloat the build context to >2GB, causing slow deployments and timeouts.

**Solution:** Always exclude these in .dockerignore:

.next/cache/
**/venv/
**/htmlcov*/
**/coverage*/

next.config.mjs

// ✅ CORRECT - Use localhost at BUILD time
const pythonBackendUrl = process.env.PYTHON_BACKEND_URL || 'http://localhost:8000';

// ❌ WRONG - Never use this old URL
// const pythonBackendUrl = 'https://atom-saas-api.fly.dev';  // DELETED APP

Dockerfile

# Both services run in same container
CMD ["./docker-entrypoint.sh", "web"]

supervisord.conf

[program:nextjs]
command=node server.js
environment=PORT=3000

[program:python]
command=python3 -m uvicorn main_api_app:app --host 0.0.0.0 --port 8000

---

NEVER DO THIS ❌

// ❌ WRONG - This app doesn't exist
const pythonBackendUrl = 'https://atom-saas-api.fly.dev';

// ❌ WRONG - Old proxy URL
rewrite: [{ source: '/api/v1/:path*', destination: 'https://atom-saas-api.fly.dev/api/v1/:path*' }]

// ❌ WRONG - Deploying to wrong app
fly deploy -a atom-saas-api  # This app doesn't exist

// ❌ WRONG - Setting environment variable to external URL
PYTHON_BACKEND_URL = "https://atom-saas-api.fly.dev"

---

ALWAYS DO THIS ✅

// ✅ CORRECT - Use localhost for internal communication
const pythonBackendUrl = process.env.PYTHON_BACKEND_URL || 'http://localhost:8000';

// ✅ CORRECT - Rewrite to internal backend
rewrite: [{ source: '/api/v1/:path*', destination: 'http://localhost:8000/api/v1/:path*' }]

// ✅ CORRECT - Deploy to the single app
fly deploy -a atom-saas

// ✅ CORRECT - Set to localhost
PYTHON_BACKEND_URL = "http://localhost:8000"

---

ARCHITECTURE DIAGRAM

Before (Dual-App - BROKEN)

User Request
    ↓
atom-saas.fly.dev (Next.js :3000)
    ↓ (proxy via internet)
atom-saas-api.fly.dev (Python :8000) ← 50+ proxy hops
    ↓
HTTP 431 Error (headers too large)

After (Single-App - WORKING)

User Request
    ↓
atom-saas.fly.dev (Container)
    ├── Next.js :3000 (supervisord)
    └── Python :8000 (supervisord)
        ↓
    localhost:8000 (internal - no proxy hops)
        ↓
    Success ✅

---

VERIFICATION CHECKLIST

When making changes, verify:

  • [ ] No references to atom-saas-api.fly.dev in code
  • [ ] PYTHON_BACKEND_URL uses http://localhost:8000 (both build.args and [env])
  • [ ] fly.toml has ROLE = 'web' for dual-process mode
  • [ ] fly.toml has app = "docker-entrypoint.sh" in [processes]
  • [ ] .dockerignore excludes .next/cache and venv (context < 200MB)
  • [ ] supervisord.conf manages both Next.js and Python
  • [ ] next.config.mjs fallback is http://localhost:8000
  • [ ] Deploying to atom-saas app (NOT atom-saas-api)

---

FILES TO CHECK

Always check these files for atom-saas-api references:

  1. next.config.mjs - Build-time rewrites
  2. fly.toml - Build args and environment variables
  3. src/middleware.ts - Request routing
  4. Any API route files - Backend URL configuration
  5. .env files - Local development configuration
  6. Documentation files - Outdated references

---

  • **50958d32** - Initial unification (2026-02-24)
  • **58dcc670** - Removed remaining atom-saas-api references (2026-04-07)
  • **00d399aa** - Fixed next.config.mjs fallback (2026-04-07)

---

WHATSAPP OAUTH CONFIGURATION

Since you asked about WhatsApp OAuth:

Webhook URL (for Meta/Facebook dashboard)

https://app.atomagentos.com/api/v1/webhooks/whatsapp

Verify Token

Set in Meta dashboard → WHATSAPP_WEBHOOK_VERIFY_TOKEN environment variable
Default: atom_whatsapp_verify_token_2024

Redirect URI (for OAuth flow)

https://app.atomagentos.com/api/integrations/whatsapp/callback

Both routes work because:

  1. Next.js receives request on port 3000
  2. Rewrites to http://localhost:8000 (internal)
  3. Python FastAPI handles webhook/OAuth callback
  4. No external proxy hops = no HTTP 431 errors

---

TROUBLESHOOTING

If you see "atom-saas-api.fly.dev" anywhere:

  1. **STOP** - Don't deploy
  2. **Search**: grep -r "atom-saas-api" .
  3. **Fix**: Replace with http://localhost:8000 or remove entirely
  4. **Verify**: Check this document for correct pattern

If API requests fail with HTTP 431:

  1. Check PYTHON_BACKEND_URL is http://localhost:8000
  2. Check no references to external proxy URLs
  3. Verify deployment is to atom-saas app only

If webhooks don't work:

  1. Verify Next.js rewrites are correct
  2. Check Python backend is running (fly ssh console -c "curl http://localhost:8000/health")
  3. Test webhook endpoint directly via SSH

---

SUMMARY

**Single App = atom-saas**

  • Next.js :3000 + Python :8000 in same container
  • Internal communication via localhost
  • No external proxy hops
  • No HTTP 431 errors

**NEVER AGAIN:**

  • atom-saas-api.fly.dev (DELETED)
  • External proxy URLs for internal communication
  • Dual-app deployment

**ALWAYS:**

  • http://localhost:8000 for PYTHON_BACKEND_URL
  • Single app deployment to atom-saas
  • Internal communication via localhost

---

Last Updated: 2026-04-13

Commit: [CURRENT_FIX]