License Management Platform - Deployment Options Analysis
Date: November 24, 2025 Status: Architecture Decision Pending Context: api.coditect.ai is already serving the Cloud IDE, Django backend needs alternative deployment
Executive Summary
During implementation, discovered that api.coditect.ai is already in production serving the Coditect Cloud IDE (Eclipse Theia) backend. The Django License Management Platform (1,595+ lines, fully functional) requires an alternative deployment strategy.
Recommended Solution: Option A - Separate Subdomain (licenses.coditect.ai)
- Fastest deployment: 2-3 days
- Clean architecture: Independent scaling and lifecycle
- Moderate cost: +$20/month for load balancer
- Low risk: No impact on existing Cloud IDE
Discovery: api.coditect.ai Current Usage
Evidence
From submodules/cloud/coditect-cloud-ide/k8s/current-ingress.yaml:
- host: api.coditect.ai
http:
paths:
- backend:
service:
name: coditect-api-v2
port:
number: 80
path: /
pathType: Prefix
What api.coditect.ai Serves
Service: coditect-api-v2 (FastAPI)
Purpose: Backend for Eclipse Theia Cloud IDE
Functions:
- IDE user authentication (JWT tokens)
- Session containerization and workspace management
- File operations for the IDE
- WebSocket connections for real-time IDE features
- Terminal/shell operations
- FoundationDB integration for persistent state
Current Status: ✅ Operational in production
Location: submodules/cloud/coditect-cloud-ide/
Option A: Separate Subdomain (RECOMMENDED)
Architecture
Deploy Django License Management Platform to licenses.coditect.ai (or license.coditect.ai).
DNS Configuration:
licenses.coditect.ai → GCP Load Balancer (NEW) → GKE Ingress → coditect-license-api service
Existing (unchanged):
api.coditect.ai → GCP Load Balancer → GKE Ingress → coditect-api-v2 service
ide.coditect.ai → GCP Load Balancer → GKE Ingress → coditect-combined-hybrid service
Technical Implementation
1. DNS Configuration:
# Create A record for licenses.coditect.ai
gcloud dns record-sets create licenses.coditect.ai. \
--type=A \
--ttl=300 \
--rrdatas=<LOAD_BALANCER_IP>
2. SSL Certificate:
# kubernetes/base/managed-certificate.yaml
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: license-api-cert
spec:
domains:
- licenses.coditect.ai
3. Kubernetes Ingress:
# kubernetes/base/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: license-api-ingress
annotations:
kubernetes.io/ingress.class: "gce"
networking.gke.io/managed-certificates: "license-api-cert"
spec:
rules:
- host: licenses.coditect.ai
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: coditect-license-api
port:
number: 80
4. Django Service:
# kubernetes/base/service.yaml
apiVersion: v1
kind: Service
metadata:
name: coditect-license-api
spec:
type: ClusterIP
selector:
app: coditect-license-api
ports:
- port: 80
targetPort: 8000
protocol: TCP
5. Django Deployment:
# kubernetes/base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: coditect-license-api
spec:
replicas: 3
selector:
matchLabels:
app: coditect-license-api
template:
metadata:
labels:
app: coditect-license-api
spec:
containers:
- name: django
image: gcr.io/coditect-cloud-infra/license-api:latest
ports:
- containerPort: 8000
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: cloudsql-db-credentials
key: connection_string
- name: REDIS_URL
valueFrom:
secretKeyRef:
name: redis-credentials
key: url
Pros
-
Clean Separation
- License API fully independent from Cloud IDE
- No routing complexity or conflicts
- Independent deployment lifecycle
-
Easy to Reason About
- Clear service boundaries
- Simpler DNS configuration
- Standard GKE ingress pattern
-
Independent Scaling
- Scale License API independently based on load
- No impact on Cloud IDE performance
- Separate monitoring and alerting
-
Low Risk
- Zero impact on existing Cloud IDE (api.coditect.ai)
- Easy rollback (delete ingress and DNS)
- Standard GCP patterns
-
Fast Deployment
- 2-3 days to production
- Minimal configuration changes
- Well-understood deployment process
Cons
-
Additional Load Balancer Cost
- +$20/month for dedicated load balancer
- Separate SSL certificate management
- Total cost: $330/month (dev) vs current $310/month
-
Multiple SSL Certificates
- Managed by Google (auto-renewal)
- But requires separate certificate resource
- Minimal operational overhead
-
DNS Propagation Time
- Initial DNS record creation: 5-10 minutes
- SSL certificate provisioning: 10-15 minutes
- Total initial setup: 15-25 minutes
Cost Analysis
| Component | Current | With Option A | Delta |
|---|---|---|---|
| GKE Cluster | $100 | $100 | $0 |
| Cloud SQL | $150 | $150 | $0 |
| Redis | $30 | $30 | $0 |
| Load Balancer | $0 | $20 | +$20 |
| SSL Certificates | $0 | $0 | $0 (managed) |
| Cloud KMS | $10 | $10 | $0 |
| Networking | $20 | $25 | +$5 |
| Total | $310 | $335 | +$25/month |
Production: +$25-30/month (6.5% increase)
Deployment Timeline
Day 1 (4 hours):
- Create Dockerfile for Django application
- Build and push image to Artifact Registry
- Create Kubernetes manifests (Deployment, Service, Ingress)
- Create ManagedCertificate resource
Day 2 (4 hours):
- Deploy to GKE
- Create DNS A record
- Wait for SSL certificate provisioning (10-15 min)
- Verify HTTPS access
Day 3 (4 hours):
- Integration testing (acquire, heartbeat, release endpoints)
- Load testing (100 concurrent requests)
- Monitoring and alerting setup
- Documentation update
Total: 12 hours over 2-3 days
Risk Assessment
| Risk | Probability | Impact | Mitigation |
|---|---|---|---|
| SSL provisioning failure | Low | Medium | Use gcloud managed certs, fallback to cert-manager |
| DNS propagation delay | Medium | Low | Use low TTL, verify with dig/nslookup |
| Load balancer cost higher than expected | Low | Low | Monitor billing dashboard |
| Routing conflicts | Very Low | Low | Completely separate domain |
Overall Risk: LOW
Option B: Path-Based Routing
Architecture
Deploy Django under api.coditect.ai/licenses/* with Kubernetes Ingress path routing.
api.coditect.ai/ → coditect-api-v2 (Cloud IDE - FastAPI)
api.coditect.ai/licenses/* → coditect-license-api (License Management - Django)
Technical Implementation
1. Modified Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: unified-api-ingress
spec:
rules:
- host: api.coditect.ai
http:
paths:
# License API (NEW - must come first for specificity)
- path: /licenses
pathType: Prefix
backend:
service:
name: coditect-license-api
port:
number: 80
# Cloud IDE API (EXISTING - catch-all)
- path: /
pathType: Prefix
backend:
service:
name: coditect-api-v2
port:
number: 80
2. Django URL Configuration:
# backend/coditect_license/urls.py
urlpatterns = [
path('licenses/admin/', admin.site.urls),
path('licenses/api/v1/licenses/', include('licenses.urls')),
]
# Full URLs become:
# https://api.coditect.ai/licenses/api/v1/licenses/acquire
# https://api.coditect.ai/licenses/api/v1/licenses/heartbeat
# https://api.coditect.ai/licenses/admin/
3. NGINX Configuration (if using):
server {
listen 8000;
server_name api.coditect.ai;
# License API
location /licenses {
proxy_pass http://django:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Pros
-
Single Domain
- Unified API endpoint (api.coditect.ai)
- Single SSL certificate
- Simpler DNS management
-
Cost Savings
- No additional load balancer ($0 vs $20/month)
- Reuse existing ingress
- Total cost: $310/month (unchanged)
-
Logical Grouping
- All APIs under api.coditect.ai
- Clear namespacing (/licenses, /, etc.)
- Easier for developers to remember
Cons
-
Complex Routing
- Path ordering matters (specificity)
- Risk of routing conflicts
- Harder to debug issues
-
Tight Coupling
- Changes to ingress affect both services
- Deployment coordination required
- Harder to rollback independently
-
Testing Complexity
- Must test both services after ingress changes
- Risk of breaking Cloud IDE routing
- More extensive integration testing
-
URL Structure
- Awkward URLs:
api.coditect.ai/licenses/api/v1/licenses/acquire - Potential for confusion (double "licenses")
- Harder to change later
- Awkward URLs:
-
Slower Deployment
- 3-4 days (more testing required)
- Must coordinate with Cloud IDE team
- Higher risk of production issues
Cost Analysis
| Component | Current | With Option B | Delta |
|---|---|---|---|
| GKE Cluster | $100 | $100 | $0 |
| Cloud SQL | $150 | $150 | $0 |
| Redis | $30 | $30 | $0 |
| Load Balancer | $0 | $0 | $0 |
| Total | $310 | $310 | $0/month |
Cost Savings vs Option A: $25/month
Deployment Timeline
Day 1 (4 hours):
- Create Dockerfile for Django application
- Build and push image to Artifact Registry
- Create Kubernetes manifests (Deployment, Service)
Day 2 (6 hours):
- Modify existing ingress configuration
- Deploy Django service to GKE
- Extensive integration testing (both services)
- Verify Cloud IDE still works
Day 3 (6 hours):
- Fix routing issues (if any)
- Load testing
- Monitoring and alerting
- Documentation update
Total: 16 hours over 3-4 days
Risk Assessment
| Risk | Probability | Impact | Mitigation |
|---|---|---|---|
| Break Cloud IDE routing | Medium | HIGH | Extensive testing, staged rollout |
| Path priority conflicts | Medium | Medium | Careful ordering, documentation |
| Difficult to rollback | Medium | Medium | Keep old ingress config, blue-green |
| Confusing URLs | High | Low | Documentation, API client wrapper |
Overall Risk: MEDIUM-HIGH
Option C: Separate GKE Cluster
Architecture
Deploy Django to a new GKE cluster dedicated to License Management.
licenses.coditect.ai → Load Balancer → NEW GKE Cluster → Django License API
Existing (unchanged):
api.coditect.ai → Load Balancer → Existing GKE Cluster → coditect-api-v2
Technical Implementation
1. New GKE Cluster:
# opentofu/modules/gke/main.tf
resource "google_container_cluster" "license_management" {
name = "coditect-license-cluster"
location = "us-central1"
node_config {
machine_type = "n1-standard-1"
preemptible = true
}
initial_node_count = 2
# Separate network for isolation
network = google_compute_network.license_vpc.name
subnetwork = google_compute_subnetwork.license_subnet.name
}
2. Separate VPC Peering:
# Access Cloud SQL from new cluster
resource "google_compute_network_peering" "license_to_cloudsql" {
name = "license-cluster-to-cloudsql"
network = google_compute_network.license_vpc.self_link
peer_network = google_compute_network.cloudsql_vpc.self_link
}
Pros
-
Complete Isolation
- Zero risk to existing Cloud IDE
- Independent Kubernetes version
- Separate control plane
-
Independent Lifecycle
- Upgrade/scale without coordination
- Separate maintenance windows
- Independent disaster recovery
-
Security Isolation
- Network-level separation
- Separate IAM policies
- Easier compliance auditing
Cons
-
High Cost
- New cluster control plane: $73/month
- New load balancer: $20/month
- New nodes: $50-100/month (2-3 nodes)
- Total additional cost: $143-193/month
-
Operational Overhead
- Manage two GKE clusters
- Double the monitoring/alerting
- Two upgrade cycles
- More complex operations
-
Resource Duplication
- Separate node pools
- Separate ingress controllers
- Duplicate tooling setup
-
Slower Deployment
- 4-5 days for cluster provisioning
- Network peering setup
- Complete GKE configuration
-
Over-Engineering
- License API is lightweight
- Doesn't justify separate cluster
- Unnecessary complexity
Cost Analysis
| Component | Current | With Option C | Delta |
|---|---|---|---|
| GKE Cluster | $100 | $100 | $0 |
| NEW GKE Cluster | $0 | $150 | +$150 |
| Cloud SQL | $150 | $150 | $0 |
| Redis | $30 | $30 | $0 |
| Load Balancer | $0 | $20 | +$20 |
| VPC Peering | $0 | $10 | +$10 |
| Total | $310 | $460 | +$150/month |
Production: +$150-200/month (48% increase)
Deployment Timeline
Day 1-2 (12 hours):
- Create OpenTofu modules for new cluster
- Deploy GKE cluster (takes 10-15 minutes)
- Configure VPC peering
- Setup kubectl contexts
Day 3 (6 hours):
- Deploy Django application
- Configure ingress and SSL
- Setup monitoring
Day 4-5 (8 hours):
- Integration testing
- Security audit
- Documentation
Total: 26 hours over 4-5 days
Risk Assessment
| Risk | Probability | Impact | Mitigation |
|---|---|---|---|
| High cost overrun | Medium | High | Monitor billing, use committed use discounts |
| Complex operations | High | Medium | Automate with scripts, documentation |
| Over-provisioned resources | High | Medium | Right-size after monitoring |
Overall Risk: MEDIUM (due to cost)
Option D: Integrate into Existing api.coditect.ai Service
Architecture
Add Django as a sidecar container or separate container in the coditect-api-v2 deployment.
api.coditect.ai → Load Balancer → GKE Ingress → coditect-api-v2 Pod
├─ FastAPI (IDE backend)
└─ Django (License API)
Technical Implementation
1. Modified Deployment (Multi-Container Pod):
apiVersion: apps/v1
kind: Deployment
metadata:
name: coditect-api-v2
spec:
template:
spec:
containers:
# Existing FastAPI container
- name: fastapi
image: gcr.io/coditect-cloud-ide/api-v2:latest
ports:
- containerPort: 8000
# NEW: Django sidecar
- name: django-license
image: gcr.io/coditect-cloud-infra/license-api:latest
ports:
- containerPort: 8001
2. Service with Multiple Ports:
apiVersion: v1
kind: Service
metadata:
name: coditect-api-v2
spec:
ports:
- name: fastapi
port: 8000
targetPort: 8000
- name: django
port: 8001
targetPort: 8001
3. Ingress Routing:
apiVersion: networking.k8s.io/v1
kind: Ingress
spec:
rules:
- host: api.coditect.ai
http:
paths:
- path: /licenses
pathType: Prefix
backend:
service:
name: coditect-api-v2
port:
number: 8001 # Django port
- path: /
pathType: Prefix
backend:
service:
name: coditect-api-v2
port:
number: 8000 # FastAPI port
Pros
-
Minimal Infrastructure Changes
- Reuse existing deployment
- No new services or ingress
- Single pod lifecycle
-
Resource Sharing
- Shared network namespace
- Shared volumes (if needed)
- Co-located for low latency
-
Zero Additional Cost
- No new load balancer
- Same node pool
- Total cost: $310/month (unchanged)
Cons
-
High Coupling
- IDE and License API share pod lifecycle
- Can't deploy independently
- Single point of failure
-
Complex Deployment
- Must coordinate with Cloud IDE team
- Risk of breaking IDE deployments
- Harder to rollback
-
Resource Contention
- FastAPI and Django compete for CPU/memory
- Harder to scale independently
- Performance monitoring complex
-
Operational Complexity
- Two frameworks in one pod
- Different logging patterns
- Debugging harder
-
Slow and Risky
- 5-6 days for testing and coordination
- High risk of production issues
- Requires deep Cloud IDE knowledge
Cost Analysis
| Component | Current | With Option D | Delta |
|---|---|---|---|
| GKE Cluster | $100 | $100 | $0 |
| Cloud SQL | $150 | $150 | $0 |
| Redis | $30 | $30 | $0 |
| Total | $310 | $310 | $0/month |
Deployment Timeline
Day 1-2 (12 hours):
- Understand coditect-api-v2 deployment
- Create multi-container deployment manifest
- Local testing
Day 3-4 (12 hours):
- Deploy to staging
- Extensive integration testing
- Fix coupling issues
Day 5-6 (8 hours):
- Production deployment (carefully)
- Monitor for issues
- Rollback plan ready
Total: 32 hours over 5-6 days
Risk Assessment
| Risk | Probability | Impact | Mitigation |
|---|---|---|---|
| Break Cloud IDE | HIGH | CRITICAL | Extensive testing, staged rollout |
| Resource contention | High | Medium | Resource limits, monitoring |
| Complex debugging | High | Medium | Structured logging, separate log streams |
| Deployment coupling | High | High | Blue-green deployment, rollback automation |
Overall Risk: HIGH
Comparison Matrix
| Criteria | Option A (Separate Subdomain) | Option B (Path-Based) | Option C (Separate Cluster) | Option D (Sidecar) |
|---|---|---|---|---|
| Deployment Time | 2-3 days ⭐ | 3-4 days | 4-5 days | 5-6 days |
| Cost | +$25/month | $0 ⭐ | +$150/month | $0 ⭐ |
| Risk | Low ⭐ | Medium-High | Medium | HIGH |
| Complexity | Low ⭐ | Medium | High | Very High |
| Independence | ⭐ Full | Partial | ⭐ Complete | None |
| Scalability | ⭐ Independent | Shared | ⭐ Independent | Coupled |
| Operational Overhead | Low ⭐ | Low | High | Medium |
| Rollback Ease | ⭐ Easy | Medium | Easy | Hard |
| Production Readiness | ⭐ High | Medium | High | Low |
Legend: ⭐ = Best in category
Recommendation
Winner: Option A - Separate Subdomain
Rationale:
- Fastest Time to Production: 2-3 days vs 3-6 days for alternatives
- Low Risk: Zero impact on existing Cloud IDE
- Clean Architecture: Independent scaling, monitoring, deployment
- Reasonable Cost: $25/month is negligible for enterprise SaaS
- Industry Standard: Separate subdomains for separate services
Trade-offs Accepted:
- +$25/month cost (6.5% increase) - acceptable for clean architecture
- Additional load balancer - managed by GCP (zero operational overhead)
- Multiple SSL certificates - automated by Google Managed Certificates
Why Not Options B, C, D?
Option B (Path-Based Routing):
- Saves $25/month but adds 1-2 days deployment time
- Medium-high risk of breaking Cloud IDE
- Complex routing leads to future maintenance burden
- Verdict: Premature optimization (saves $300/year, costs weeks of debugging)
Option C (Separate Cluster):
- Over-engineered for a lightweight Django API
- 48% cost increase ($150/month) not justified
- Operational overhead of managing two clusters
- Verdict: Unnecessary complexity
Option D (Sidecar Integration):
- Highest risk (could break production IDE)
- Tight coupling makes future changes hard
- 5-6 days deployment with extensive testing
- Verdict: Anti-pattern for independent services
Implementation Plan (Option A)
Phase 1: Infrastructure Setup (Day 1, 4 hours)
1. Create Kubernetes Manifests:
mkdir -p kubernetes/license-api/{base,overlays/dev,overlays/prod}
# Create deployment, service, ingress, managed-certificate
# See Technical Implementation section for YAML examples
2. Create Dockerfile:
# backend/Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
# Run migrations (in Cloud Build)
# CMD is gunicorn for production
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "coditect_license.wsgi:application"]
3. Build and Push Image:
cd backend
gcloud builds submit --tag gcr.io/coditect-cloud-infra/license-api:v1
Phase 2: Deployment (Day 2, 4 hours)
1. Deploy to GKE:
kubectl apply -k kubernetes/license-api/overlays/dev/
2. Create DNS Record:
gcloud dns record-sets create licenses.coditect.ai. \
--type=A \
--ttl=300 \
--rrdatas=$(kubectl get ingress license-api-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
3. Wait for SSL Certificate:
# Takes 10-15 minutes
kubectl describe managedcertificate license-api-cert
# Wait for Status: Active
4. Verify HTTPS Access:
curl -I https://licenses.coditect.ai/api/v1/licenses/acquire
# Should return 400 (missing request body - expected)
Phase 3: Testing & Monitoring (Day 3, 4 hours)
1. Integration Tests:
python tests/test_license_api.py
# Test acquire, heartbeat, release endpoints
2. Load Testing:
# 100 concurrent license acquisitions
ab -n 1000 -c 100 -p acquire.json \
https://licenses.coditect.ai/api/v1/licenses/acquire
3. Monitoring Setup:
# Prometheus ServiceMonitor
kubectl apply -f kubernetes/license-api/monitoring/service-monitor.yaml
# Grafana dashboard
# Import dashboard JSON
4. Documentation Update:
- Update implementation-status.md with deployment details
- Update ADR-003 with final decision
- Create DEPLOYMENT-POSTMORTEM.md
Phase 4: Production Rollout (Post-MVP)
1. Deploy to Staging:
kubectl apply -k kubernetes/license-api/overlays/staging/
2. Smoke Tests:
curl -X POST https://licenses-staging.coditect.ai/api/v1/licenses/acquire \
-H "Content-Type: application/json" \
-d '{"license_key": "test-key", "hardware_id": "test-hw", "user_email": "test@example.com"}'
3. Deploy to Production:
# Manual approval required
kubectl apply -k kubernetes/license-api/overlays/prod/
Next Steps
Immediate Actions:
- ✅ Human Decision Required: Approve Option A (or select alternative)
- ⏸️ Create Dockerfile for Django application
- ⏸️ Create Kubernetes manifests (Deployment, Service, Ingress, ManagedCertificate)
- ⏸️ Build and push Docker image to Artifact Registry
- ⏸️ Deploy to GKE and verify HTTPS access
Timeline: 2-3 days to production-ready deployment
Appendix: Alternative Subdomain Names
If licenses.coditect.ai is not preferred:
Option A1: license.coditect.ai (singular)
- Pros: Shorter, grammatically correct for "License API"
- Cons: Slightly less intuitive
Option A2: licensing.coditect.ai
- Pros: Clear purpose, professional
- Cons: Longer domain name
Option A3: lm.coditect.ai (License Management)
- Pros: Very short
- Cons: Abbreviation not intuitive
Recommended: licenses.coditect.ai (plural matches resource naming convention)
Document Version: 1.0 Author: AI Agent (Claude) with human oversight Review Status: Pending human approval Next Review: After deployment strategy decision