Your Azure bill hit €12,000 last month — again — and half your containers are sitting idle at 8% CPU. You are not alone. Across the Nordics, small and mid-sized companies that moved to the cloud five or six years ago are doing the same math and arriving at the same uncomfortable conclusion: the cloud is costing more than it should, and the value proposition has shifted.
This is not an anti-cloud manifesto. Some workloads genuinely belong there. But if you are running predictable, steady-state applications on managed services you barely use, on-premises infrastructure deserves a serious look. I recently migrated a full .NET backend API and Angular frontend stack from Azure to on-premise Rocky Linux servers for a Nordic client — and the numbers told a clear story.
Why Nordic SMBs Are Re-Evaluating Cloud
Three forces are driving the conversation.
Cost. Cloud pricing was designed for elastic workloads — bursty traffic, unpredictable demand, fast experimentation. Most Nordic SMBs run the opposite: stable line-of-business applications with predictable load. You are paying a premium for elasticity you never use. When I ran the numbers for a 20-person development team's infrastructure, the cloud bill was roughly 3x what the same capacity cost on owned hardware over a three-year horizon.
Data sovereignty and GDPR. Nordic companies handle data subject to GDPR, and increasingly face questions about where that data physically lives. Azure's Norway East and Sweden Central regions help, but they do not eliminate the compliance overhead of proving your data stays within the right jurisdiction. On-premise gives you a simple answer: it is in the server room down the hall.
Vendor lock-in. Every managed service you adopt — Azure Service Bus, AWS Lambda, Google Cloud Run — adds a dependency that makes leaving harder. After a few years, "multi-cloud" is a fantasy and "exit" is a project nobody wants to scope. Getting ahead of this is cheaper than getting out of it later.
Decision Framework: What Belongs On-Prem vs. What Stays in the Cloud
Not everything should come back. Here is how I think about it:
Move on-prem when:
- The workload has predictable, steady resource consumption
- You have (or can hire) someone who can maintain Linux servers and Docker
- The application handles sensitive data that benefits from physical control
- You are paying for managed services (e.g., Azure SQL, App Service) that a self-hosted equivalent covers at a fraction of the cost
Keep in the cloud when:
- Traffic is genuinely spiky or seasonal (e-commerce flash sales, campaign-driven SaaS)
- You need global distribution and edge presence
- The team has zero infrastructure experience and cannot invest in building it
- You are using cloud-native services that have no practical self-hosted equivalent (e.g., machine learning inference APIs, global CDN)
The grey zone: Many workloads fall in between. For these, run the TCO comparison below before deciding. Do not guess — calculate.
Cloud to On-Premise Migration Checklist
I have done this migration twice in production. Here is the checklist I wish I had the first time.
Phase 1: Inventory and Assessment (2–4 weeks)
- List every service and resource in your cloud account. Not just compute — storage, DNS, secrets, queues, scheduled jobs, monitoring. Export your cloud provider's resource list. Azure:
az resource list. AWS:aws resourcegroupstaggingapi get-resources. - Map dependencies. Which services talk to which? Draw the arrows. Every managed service you use (e.g., Azure Service Bus) needs a self-hosted replacement (e.g., RabbitMQ) or a redesign.
- Identify stateful components. Databases, file storage, caches. These are your hardest migration targets. Plan them first.
- Baseline current performance. Document response times, throughput, and error rates before migration. You need this to validate after cutover.
- Audit cloud-specific SDK usage. Search your codebase for cloud provider SDKs. Each call is a potential migration task.
Phase 2: Infrastructure Preparation (2–6 weeks)
- Provision hardware. For a typical Nordic SMB, four VMs or bare-metal servers cover most needs: DEV, TEST, PROD, and a TOOLS server (for CI/CD agents, container registry, monitoring). Budget €15,000–€30,000 for three-year hardware, depending on spec.
- Choose your OS. Rocky Linux 9 or Ubuntu 22.04 LTS. Both are solid. I use Rocky Linux for production servers — it is the CentOS successor and has a 10-year support cycle.
- Set up configuration management. Ansible is the right choice for teams under 200 people. It is agentless, readable, and does not require a PhD to operate. Write playbooks for every server role.
- Deploy your container stack. Docker Compose for orchestration at SMB scale. Kubernetes is overkill unless you are running 50+ services — and even then, think twice.
- Stand up supporting services. Container registry (Harbor), monitoring (Grafana + Loki + Promtail), secrets management (Vaultwarden or HashiCorp Vault), reverse proxy (Nginx with SSL termination).
Phase 3: Application Migration (4–8 weeks)
- Containerize everything that is not already containerized. If your .NET app runs on Azure App Service, it needs a Dockerfile.
- Replace managed services one by one. Azure SQL → PostgreSQL. Azure Service Bus → RabbitMQ. Azure Blob Storage → MinIO. Test each replacement in isolation.
- Update CI/CD pipelines. Your build agents need to push to your private registry and deploy to your servers, not to Azure. Self-hosted Azure DevOps agents or Gitea + Drone CI both work.
- Migrate data. Schedule a maintenance window. For databases, use
pg_dump/pg_restoreor the equivalent. Test the restore on your target environment before the real cutover. - Validate. Compare against your Phase 1 baselines. Response times, error rates, throughput. If something regressed, fix it before going live.
Phase 4: Cutover and DNS Switch (1 day)
- Final data sync during a planned maintenance window.
- Switch DNS to point to the on-prem servers. Keep the cloud environment running in parallel for 1–2 weeks as a rollback option.
- Monitor aggressively for the first 72 hours. Grafana dashboards and alerts should be in place before cutover, not after.
Common Pitfalls
I have hit all of these. Learn from my mistakes.
Underestimating bandwidth requirements. Cloud providers give you fast, free inter-service networking. On-prem, your network is your own problem. Make sure your internal network can handle the traffic between services. A 1 Gbps switch is the minimum; 10 Gbps is cheap insurance.
Licensing traps. Some software (looking at you, SQL Server) has on-premise licensing that costs more than the cloud version. Check every license before committing. PostgreSQL, Redis, and RabbitMQ are free — and for most Nordic SMBs, they are more than enough.
The "we will figure out backups later" mistake. On Azure, backups are mostly automatic. On-prem, they are your responsibility from day one. Set up automated backups to an offsite location before you migrate production data. Not after. Before.
Ignoring the human factor. Someone needs to be on call for hardware failures. In the cloud, you do not think about disk failures or power outages. On-prem, you do. If your team does not want this responsibility, either hire for it or use a colocation facility with managed hardware.
Trying to replicate the cloud on-prem. Do not install Kubernetes, a service mesh, and a cloud-native API gateway just because you had them in Azure. Start simple: Docker Compose, Nginx, PostgreSQL. Add complexity only when the workload demands it.
Real Cost Comparison: 3-Year TCO
Here is a simplified but realistic comparison for a Nordic SMB running a .NET backend API, Angular frontend, PostgreSQL database, message queue, and monitoring — supporting a 20-person development team.
Cloud (Azure)
Item
Monthly Cost
3-Year Total
App Service (2x B2, prod + staging)
€400
€14,400
Azure SQL (S3)
€500
€18,000
Azure Service Bus (Standard)
€50
€1,800
Blob Storage (500 GB)
€30
€1,080
Azure DevOps (5 parallel jobs)
€200
€7,200
Monitoring (Application Insights, Log Analytics)
€250
€9,000
Networking (bandwidth, DNS, load balancer)
€150
€5,400
Total
€1,580/mo
€56,880
On-Premises
Item
Cost
3-Year Total
4x servers (Dell PowerEdge T350 or equivalent)
one-time €20,000
€20,000
Colocation or server room power/cooling
€200/mo
€7,200
Internet (dedicated 1 Gbps, Nordic ISP)
€300/mo
€10,800
Software licenses (all open source)
€0
€0
Offsite backup storage (Backblaze B2, 1 TB)
€5/mo
€180
Additional sysadmin time (~4 hrs/mo at €100/hr)
€400/mo
€14,400
Total
€52,580
3-year savings: approximately €4,300. That is not dramatic — but it compounds. The on-prem cost is mostly front-loaded (hardware), while cloud costs only go up. By year five, the gap widens to roughly €25,000–€35,000 because the hardware is already paid for.
And this comparison is conservative. Many Nordic SMBs I talk to are spending €3,000–€8,000/month on cloud — at which point the on-prem savings are significant from year one.
When NOT to Do This
I would not recommend on-prem migration if:
- Your team has fewer than three developers and zero ops experience. The learning curve will eat your savings.
- Your application is genuinely elastic — scaling from 2 to 200 instances based on demand.
- You are a startup that might pivot next quarter. Do not buy hardware for a product that might not exist in six months.
- You are in a regulated industry that requires specific cloud certifications you cannot replicate on-prem (rare in the Nordics, but worth checking).
Next Steps
If the numbers look interesting for your situation, start with the inventory in Phase 1. You do not need to commit to anything — just map what you have and run your own TCO comparison with real figures.
I have put together a cloud migration checklist template you can download, along with production-ready Ansible playbook templates for the base server setup.
Or if you want to talk through your specific situation — whether migration makes sense, what it would cost, and how long it would take — book a free 30-minute call. No pitch, just an honest assessment from someone who has done it.
Top comments (0)