Why Infrastructure Decisions Are Business Decisions
As CTO and Co-founder of Datox, I’ve always believed that infrastructure decisions are business decisions. When we started building our Datox platform, Azure App Service was the fastest way to get to market. It allowed us to focus on product, customers, and regulatory workflows without over-engineering from day one. But as Datox evolved, serving more customers, supporting multi-tenant deployments, and expanding into different Azure subscriptions, our architecture needed to evolve too.
This post is the story of how and why we migrated from Azure App Service to Azure Container Apps. It was a strategic move that reduced our non-production costs by 90%, enabled true independent scaling, simplified customer deployments, and positioned Datox for a cloud-native, enterprise-ready future.
What Are Azure Container Apps?
Azure Container Apps is a fully managed serverless platform for running containerized applications. Built on Kubernetes, it abstracts away infrastructure complexity while providing powerful features for modern application development. Think of it as the sweet spot between Platform as a Service (PaaS) simplicity and Infrastructure as a Service (IaaS) flexibility.
Key Characteristics:
- Serverless container hosting
- Built-in autoscaling (scale to zero capability)
- Microservices-native architecture
- Event-driven scaling with KEDA (Kubernetes Event-Driven Autoscaling)
- Integrated ingress and service discovery
- Built-in traffic splitting for blue-green deployments
Business Drivers Behind the Migration
As our product matured, we faced several strategic business requirements:
- Multi-tenancy: Customers wanted to deploy our solution in their own Azure subscriptions or on-premises.
- Cloud-native architecture: Need for portable, containerized deployments that could run anywhere
- Independent scaling: Frontend and backend services had different load patterns and needed to scale independently
- Cost optimization: Non-production environments (dev, staging, demo) were incurring costs 24/7 even when idle
- Microservices evolution: Growing need to break down the monolith into independently deployable services
Technical Constraints with Azure App Service
While App Service helped us move fast early on, we started hitting structural limitations:
- Always-on pricing meant we paid for idle development environments overnight and on weekends
- Difficult to package and deploy the entire stack to customer clouds
- Frontend (React SPA) and backend (Python FastAPI) had to scale together despite different traffic patterns
- Limited support for running multiple interconnected services efficiently
- Complex custom domain and SSL management across multiple environments
The Migration Strategy
We made the strategic decision to containerize our entire application stack and migrate to Azure Container Apps. The migration involved:
-
Containerization
- Created multi-stage Dockerfiles for frontend (React) and backend (Python FastAPI)
- Containerized Azure Functions for background processing and SignalR real-time messaging
- Optimized images using Alpine Linux and multi-stage builds
-
Infrastructure as Code
- Automated deployment pipelines with GitHub Actions
- Environment-specific configurations using build arguments and runtime environment variables
- Secret management via Azure Key Vault integration
-
Multi-environment strategy
- Development, Staging, and Production environments
- Each environment is independently scalable and configurable
- Branch-based deployment automation (dev branch → dev environment, main → production)
Measurable Results
The migration delivered significant benefits across cost, operations, and business capabilities:
| Metric | Before (App Service) | After (Container Apps) | Improvement |
|---|---|---|---|
| Monthly Cost (Non-Prod) | ~$450 (3 environments, always-on) | ~$45 (scale to zero overnight/weekends) | 90% reduction |
| Deployment Time | 8-12 minutes per environment | 3-5 minutes per environment | 50% faster |
| Frontend Scaling | Coupled with backend | Independent (0-10 replicas) | Independent scaling |
| Backend Scaling | Coupled with frontend | Independent (0-30 replicas) | Independent scaling |
| Cold Start Time | N/A (always-on) | <10 seconds from zero | Acceptable trade-off |
| Environment Spin-up | 2-3 hours (manual setup) | 15 minutes (automated) | 88% faster |
| Customer Deployment | 1-2 days (complex process) | 2-4 hours (containerized) | 80% reduction |
| SSL Certificate Management | Manual per environment | Automated with Container Apps | Zero manual effort |
| Service Discovery | Manual configuration | Built-in internal ingress | Automatic |
| Infrastructure Overhead | Medium (App Service plans) | Low (serverless) | Minimal management |
What key benefits have been realized
1. Cost Optimization
- Development and demo environments now scale to zero during off-hours
- Production uses dedicated capacity for consistent performance
- Eliminated over-provisioning—each service sized appropriately
2. Customer Deployments
- Entire platform packaged as container images
- Customers deploy to their Azure subscriptions in hours, not days
- Consistent experience across all customer environments
- Easy version upgrades via container image updates
3. Independent Scaling
- Frontend scales based on HTTP requests (user traffic)
- Backend scales based on API load and queue depth
- Azure Functions scale based on message queue length
- Each service optimized for its workload pattern
4. Developer Productivity
- Local development with Docker Compose mirrors production exactly
- CI/CD pipelines deploy to any environment with branch push
- No more "works on my machine" issues
- Faster iteration cycles for development team
5. Operational Excellence
- Built-in health checks and auto-recovery
- Application Insights integration for centralized monitoring
- Log Analytics for troubleshooting across all services
- Blue-green deployments via traffic splitting
6. AI-Ready Architecture
As Datox evolved, our AI workloads expanded from document processing to real-time compliance validation and background data enrichment.
Azure Container Apps significantly improved how we run and scale our AI services:
- AI workers scale independently based on queue depth and workload
- Background model execution runs in isolated containers
- No need to over-provision compute for sporadic AI spikes
- Easier integration with Azure AI services (Azure Foundry) and GPU-enabled environments (when needed)
- Faster experimentation with new AI services without impacting core APIs
Previously, under App Service, AI workloads were tightly coupled with the main application runtime. Now, they are independently deployable and scalable microservices.
This architectural shift allowed us to:
- Deploy AI features faster
- Control AI infrastructure costs more precisely
- Improve reliability during heavy document-processing workloads
- Prepare for future GPU-backed and high-throughput AI services
Lessons Learned
What Worked Well:
- Multi-stage Docker builds kept images small and secure
- Scale-to-zero for non-production saved significant costs
- GitHub Actions integration made CI/CD seamless
- Internal ingress simplified service-to-service communication
Challenges Overcome:
- Initial cold start optimization required tuning image sizes
- Secret management required Key Vault integration planning
- Team needed Docker knowledge (addressed with training)
- Database connection pooling configuration for scaled replicas
Would We Do It Again?
Absolutely. The migration paid for itself in the first quarter through cost savings alone, and the business benefits, especially customer deployments, have been transformative for our go-to-market strategy. In the next post, I’ll go hands-on and show you exactly how to make a similar migration from containerization to infrastructure setup and CI/CD.
Top comments (1)
Love this! "Infrastructure decisions are business decisions" — that one line says everything. As someone exploring Azure for my own projects, this migration story is incredibly valuable. Would love to know more about the performance differences you noticed after moving to Container Apps. Thanks for sharing your experience as a founder!