Skip to main content

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/


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

  1. Clean Separation

    • License API fully independent from Cloud IDE
    • No routing complexity or conflicts
    • Independent deployment lifecycle
  2. Easy to Reason About

    • Clear service boundaries
    • Simpler DNS configuration
    • Standard GKE ingress pattern
  3. Independent Scaling

    • Scale License API independently based on load
    • No impact on Cloud IDE performance
    • Separate monitoring and alerting
  4. Low Risk

    • Zero impact on existing Cloud IDE (api.coditect.ai)
    • Easy rollback (delete ingress and DNS)
    • Standard GCP patterns
  5. Fast Deployment

    • 2-3 days to production
    • Minimal configuration changes
    • Well-understood deployment process

Cons

  1. Additional Load Balancer Cost

    • +$20/month for dedicated load balancer
    • Separate SSL certificate management
    • Total cost: $330/month (dev) vs current $310/month
  2. Multiple SSL Certificates

    • Managed by Google (auto-renewal)
    • But requires separate certificate resource
    • Minimal operational overhead
  3. DNS Propagation Time

    • Initial DNS record creation: 5-10 minutes
    • SSL certificate provisioning: 10-15 minutes
    • Total initial setup: 15-25 minutes

Cost Analysis

ComponentCurrentWith Option ADelta
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

RiskProbabilityImpactMitigation
SSL provisioning failureLowMediumUse gcloud managed certs, fallback to cert-manager
DNS propagation delayMediumLowUse low TTL, verify with dig/nslookup
Load balancer cost higher than expectedLowLowMonitor billing dashboard
Routing conflictsVery LowLowCompletely 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

  1. Single Domain

    • Unified API endpoint (api.coditect.ai)
    • Single SSL certificate
    • Simpler DNS management
  2. Cost Savings

    • No additional load balancer ($0 vs $20/month)
    • Reuse existing ingress
    • Total cost: $310/month (unchanged)
  3. Logical Grouping

    • All APIs under api.coditect.ai
    • Clear namespacing (/licenses, /, etc.)
    • Easier for developers to remember

Cons

  1. Complex Routing

    • Path ordering matters (specificity)
    • Risk of routing conflicts
    • Harder to debug issues
  2. Tight Coupling

    • Changes to ingress affect both services
    • Deployment coordination required
    • Harder to rollback independently
  3. Testing Complexity

    • Must test both services after ingress changes
    • Risk of breaking Cloud IDE routing
    • More extensive integration testing
  4. URL Structure

    • Awkward URLs: api.coditect.ai/licenses/api/v1/licenses/acquire
    • Potential for confusion (double "licenses")
    • Harder to change later
  5. Slower Deployment

    • 3-4 days (more testing required)
    • Must coordinate with Cloud IDE team
    • Higher risk of production issues

Cost Analysis

ComponentCurrentWith Option BDelta
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

RiskProbabilityImpactMitigation
Break Cloud IDE routingMediumHIGHExtensive testing, staged rollout
Path priority conflictsMediumMediumCareful ordering, documentation
Difficult to rollbackMediumMediumKeep old ingress config, blue-green
Confusing URLsHighLowDocumentation, 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

  1. Complete Isolation

    • Zero risk to existing Cloud IDE
    • Independent Kubernetes version
    • Separate control plane
  2. Independent Lifecycle

    • Upgrade/scale without coordination
    • Separate maintenance windows
    • Independent disaster recovery
  3. Security Isolation

    • Network-level separation
    • Separate IAM policies
    • Easier compliance auditing

Cons

  1. 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
  2. Operational Overhead

    • Manage two GKE clusters
    • Double the monitoring/alerting
    • Two upgrade cycles
    • More complex operations
  3. Resource Duplication

    • Separate node pools
    • Separate ingress controllers
    • Duplicate tooling setup
  4. Slower Deployment

    • 4-5 days for cluster provisioning
    • Network peering setup
    • Complete GKE configuration
  5. Over-Engineering

    • License API is lightweight
    • Doesn't justify separate cluster
    • Unnecessary complexity

Cost Analysis

ComponentCurrentWith Option CDelta
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

RiskProbabilityImpactMitigation
High cost overrunMediumHighMonitor billing, use committed use discounts
Complex operationsHighMediumAutomate with scripts, documentation
Over-provisioned resourcesHighMediumRight-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

  1. Minimal Infrastructure Changes

    • Reuse existing deployment
    • No new services or ingress
    • Single pod lifecycle
  2. Resource Sharing

    • Shared network namespace
    • Shared volumes (if needed)
    • Co-located for low latency
  3. Zero Additional Cost

    • No new load balancer
    • Same node pool
    • Total cost: $310/month (unchanged)

Cons

  1. High Coupling

    • IDE and License API share pod lifecycle
    • Can't deploy independently
    • Single point of failure
  2. Complex Deployment

    • Must coordinate with Cloud IDE team
    • Risk of breaking IDE deployments
    • Harder to rollback
  3. Resource Contention

    • FastAPI and Django compete for CPU/memory
    • Harder to scale independently
    • Performance monitoring complex
  4. Operational Complexity

    • Two frameworks in one pod
    • Different logging patterns
    • Debugging harder
  5. Slow and Risky

    • 5-6 days for testing and coordination
    • High risk of production issues
    • Requires deep Cloud IDE knowledge

Cost Analysis

ComponentCurrentWith Option DDelta
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

RiskProbabilityImpactMitigation
Break Cloud IDEHIGHCRITICALExtensive testing, staged rollout
Resource contentionHighMediumResource limits, monitoring
Complex debuggingHighMediumStructured logging, separate log streams
Deployment couplingHighHighBlue-green deployment, rollback automation

Overall Risk: HIGH


Comparison Matrix

CriteriaOption A (Separate Subdomain)Option B (Path-Based)Option C (Separate Cluster)Option D (Sidecar)
Deployment Time2-3 days ⭐3-4 days4-5 days5-6 days
Cost+$25/month$0 ⭐+$150/month$0 ⭐
RiskLow ⭐Medium-HighMediumHIGH
ComplexityLow ⭐MediumHighVery High
Independence⭐ FullPartial⭐ CompleteNone
Scalability⭐ IndependentShared⭐ IndependentCoupled
Operational OverheadLow ⭐LowHighMedium
Rollback Ease⭐ EasyMediumEasyHard
Production Readiness⭐ HighMediumHighLow

Legend: ⭐ = Best in category


Recommendation

Winner: Option A - Separate Subdomain

Rationale:

  1. Fastest Time to Production: 2-3 days vs 3-6 days for alternatives
  2. Low Risk: Zero impact on existing Cloud IDE
  3. Clean Architecture: Independent scaling, monitoring, deployment
  4. Reasonable Cost: $25/month is negligible for enterprise SaaS
  5. 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:

  1. Human Decision Required: Approve Option A (or select alternative)
  2. ⏸️ Create Dockerfile for Django application
  3. ⏸️ Create Kubernetes manifests (Deployment, Service, Ingress, ManagedCertificate)
  4. ⏸️ Build and push Docker image to Artifact Registry
  5. ⏸️ 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