A practical guide to moving off PaaS platforms and running production workloads you actually own.
You started on Railway — or Render, or Fly.io or any similar solution. That was the right call. You had a prototype to ship, a team of two, and zero interest in managing infrastructure. These platforms made that possible. They still deserve credit for that. But something shifted. Your user count crossed a threshold. A paying customer called during an outage. Your monthly PaaS bill hit a number that made your CFO ask questions. Or maybe you've been burned enough times by cold starts, failed deployments, or a shared infrastructure incident that had nothing to do with your code.
Today's Railway outage causes a series of outages across many small businesses. Revenue loss is a real thing. You're frustrated.
That frustration is a signal. It means the abstraction that once helped you is now working against you.
This article is for teams in that position: past prototype, running real production traffic, and wondering if there's a better place to run.
What these platforms do well — and where they stop
Railway, Render, and Fly.io are genuinely good products for what they're designed to do. They remove infrastructure decisions from your path so you can focus on application code. For an early-stage team, that's a meaningful advantage.
The problems tend to show up in a predictable sequence:
Reliability at the shared layer. These platforms run on shared infrastructure. When their control plane has issues, your service has issues. You can read the incident postmortems, but the underlying architecture means you're not in control. For a prototype, that's fine. For a production service with SLAs, it becomes a business risk.
Cost structure that doesn't scale. PaaS pricing is priced for convenience, not for efficiency. At low usage, the cost is reasonable. As your workload grows — more services, more traffic, more environments — the per-unit cost stays flat or increases while the equivalent cost on raw cloud infrastructure falls significantly. This isn't a complaint about pricing; it's just how the model works.
Operational limits you can't negotiate around. Want persistent volumes with specific IOPS? Custom networking topology? A deployment pipeline that integrates with your internal tooling in a specific way? On a PaaS, you work within what's available. You don't get to rewrite the rules.
Organizational risk. These are smaller companies. Their roadmaps change. Their pricing changes. The Heroku story — once the go-to platform for a generation of startups, now in sustaining engineering mode — should be a useful reference point. Dependency on a single vendor's platform is a risk that grows as your own company grows.
None of this means you made a mistake starting there. It means you've grown past what the abstraction was built for.
Why Kubernetes, specifically
Kubernetes has a reputation for complexity that was earned in 2018 and never quite shed. The honest answer is that it's still more complex to set up than a PaaS — but the gap has narrowed dramatically, and the operational complexity at scale is now lower, not higher, than managing a sprawling set of PaaS services.
A few things have changed:
EKS, GKE, and AKS have absorbed most of the control plane complexity. You don't manage etcd. You don't manually upgrade API servers. The cloud providers do that. What you're left with is a well-documented, vendor-neutral API for running workloads.
Tooling like ArgoCD, Helm, and Kustomize has made GitOps genuinely accessible. Your entire deployment state lives in git. Rollbacks are a git revert. Drift between environments is detectable and fixable. You get the audit trail you never had on Railway.
AI-assisted operations have changed what a small team can manage. Infrastructure automation that used to require a dedicated platform engineering team can now be scaffolded, documented, and maintained by application engineers with AI tooling. We'll come back to this.
The result is a platform you own, with costs you control, that doesn't have a shared infrastructure ceiling above you.
The pricing reality: Railway versus Kubernetes on AWS
Let's use specific numbers. These are illustrative but based on typical configurations — your actual numbers will vary depending on region, usage patterns, and architecture choices.
A representative workload
Say you're running:
- 5 backend services (Node.js / Python / Go, mixed)
- 2 worker processes
- 1 PostgreSQL database (10 GB active, 50 GB total)
- 1 Redis instance
- 3 environments: production, staging, development
- ~500 GB egress/month
Railway cost estimate
Railway's Pro plan charges per resource consumed, with a $20/seat base:
| Component | Monthly cost |
|---|---|
| 5 backend services (512 MB RAM, 0.5 vCPU each, ~720 hrs) | ~$180 |
| 2 workers (256 MB RAM, 0.25 vCPU each) | ~$45 |
| PostgreSQL (managed, 10 GB) | ~$25 |
| Redis (managed, 1 GB) | ~$20 |
| Staging environment (50% of prod) | ~$110 |
| Dev environment (minimal) | ~$40 |
| Egress (500 GB) | ~$50 |
| Estimated total | ~$470/month |
This is conservative. Teams report paying $600–$1,200+/month once they add more services, database storage, or multiple team environments.
Kubernetes on AWS (EKS) cost estimate
The equivalent on EKS in us-east-1, using a right-sized node group:
| Component | Monthly cost |
|---|---|
| EKS cluster control plane | $73 |
| 3x t3.medium nodes (prod, ~$0.0416/hr each) | ~$90 |
| 1x t3.small node (staging/dev) | ~$15 |
| RDS PostgreSQL t3.micro (or self-hosted CloudNativePG — free) | $25–$0 |
| ElastiCache Redis t3.micro (or self-hosted — free) | $25–$0 |
| ALB load balancer | ~$20 |
| NAT Gateway | ~$35 |
| Egress (500 GB) | ~$45 |
| S3, ECR, misc | ~$10 |
| Estimated total (managed DBs) | ~$338/month |
| Estimated total (self-hosted DBs on K8s) | ~$288/month |
At this workload size, you save roughly $150–$200/month. At 2x the workload, the gap widens considerably — Kubernetes scales by adding nodes with linear cost, while PaaS costs often scale super-linearly because you're paying per-service rather than per-compute-unit.
At scale, the difference is more pronounced
| Monthly workload | Railway (est.) | EKS (est.) | Annual savings |
|---|---|---|---|
| Current (5 services) | $470 | $300 | ~$2,000 |
| 2x growth | $900 | $450 | ~$5,400 |
| 5x growth | $2,100 | $800 | ~$15,600 |
The crossover point where Kubernetes becomes meaningfully cheaper usually sits around $400–600/month in PaaS spend. Below that, the operational overhead of self-management probably isn't worth it. Above it, the economics increasingly favor Kubernetes — and the reliability and control arguments become much stronger too.
What reliability actually looks like on Kubernetes
"Reliability" is easy to promise. Here's what it means in concrete terms when you own your cluster:
You control the blast radius. On a PaaS, a bad deployment or a noisy-neighbor situation can take down your service regardless of what your code does. On Kubernetes, you define resource limits, pod disruption budgets, and liveness/readiness probes. Your deployment failing doesn't affect your database. Your database having a hiccup doesn't kill your web tier.
You control the rollout. With ArgoCD and a GitOps model, deployments are declarative. You describe the desired state; the system reconciles to it. Want to canary 5% of traffic to a new version before cutting over? That's a one-line change in your GitOps repo. Want to roll back instantly? Revert the commit.
You get real observability. Prometheus, Grafana, and OpenTelemetry running in your cluster give you metrics and traces that are yours — not a 30-day log retention window on a SaaS dashboard. You can alert on what matters, store what you need, and query it without paying per-seat or per-query.
You understand what's running. On a PaaS, "deploy" is a black box. On Kubernetes, you know exactly what's running where, with what resources, connected to what. When something breaks at 2am, you have the tools to understand why.
You can go multi-cloud or setup DR environment. Many past failures in PaaS were happening because of underlying cloud provider issues or PaaS account specific issues like hitting a ceiling on quotas, or getting their account suspended. If you design for failure, you can control the reliability.
GitOps: the deployment model that actually works at scale
GitOps is not a new concept, but it's worth explaining clearly because it solves problems that PaaS platforms never fully addressed.
The idea is simple: your git repository is the single source of truth for what runs in production. ArgoCD (or Flux) watches that repository and reconciles the cluster state to match. You don't push to deploy — you merge to deploy. The deployment is the git commit.
What this gives you:
- Every change to production is tracked in git history, with author, timestamp, and diff
- You can reproduce any past state by checking out the corresponding commit
- Drift between what's in git and what's running is detectable and auto-correctable
- Multiple environments (dev, staging, prod) have their own branches or overlays, with promotions as explicit pull requests
- Your entire infrastructure review process is a code review process
Teams that have shipped on Railway for years often describe their first month on GitOps as "realizing we never actually knew what was running in production." That's not a criticism — it's a reflection of how much PaaS platforms abstract away. GitOps trades that abstraction for legibility.
AI-assisted operations: what "self-hosting becomes easier" actually means
The standard argument against self-hosting is that it requires dedicated infrastructure expertise. That argument is less true than it was three years ago.
AI tooling — coding assistants, infrastructure reasoning, runbook generation — has materially lowered the floor for managing a Kubernetes cluster. Not to zero, but to a level accessible to an engineering team that isn't exclusively focused on platform work.
In practice this looks like:
- Generating Helm charts and Kubernetes manifests from application specs, with sensible defaults, reviewed rather than written from scratch
- Automatic runbook drafting based on alert conditions — when a pod OOMKills, the system generates the investigation steps before an engineer picks it up
- Infrastructure-as-code generation (Terraform, CDK) for new environments, reviewed and applied rather than written manually
- Incident analysis: feeding cluster events and logs to an AI assistant to narrow root cause before a human digs in
CloudRaft's accelerator builds on top of this: a pre-configured Kubernetes platform with GitOps, observability, security policies, and secret management already wired up — so your team inherits a working platform rather than starting from a blank cluster.
The point is not that AI replaces infrastructure expertise. It's that a small team with good tooling can now operate a production Kubernetes cluster that would have required a 3-5 person platform team five years ago.
The migration path: what it actually takes
This is where a lot of articles wave their hands. Here's a more honest picture of what migration involves:
Phase 1: Assessment (1–2 weeks)
Before writing a single Kubernetes manifest, you need to understand what you're migrating. How many services? What are their dependencies? What does the data model look like? Where are the stateful components? Which services are candidates for the first wave versus which need re-architecture first?
The output of this phase is a migration plan with explicit risk callouts, not a generic "lift and shift" assumption.
Phase 2: Platform setup (1–2 weeks)
The target Kubernetes cluster needs to exist and be functional before you migrate anything. This means:
- Cluster provisioning (EKS, GKE, or AKS depending on your cloud)
- Networking: ingress controller, internal DNS, load balancer
- GitOps setup: ArgoCD or Flux, connected to your repository
- Secret management: External Secrets Operator or similar
- Observability: Prometheus + Grafana stack, or a managed alternative
- CI pipeline: container builds pushing to your registry, triggering ArgoCD syncs
With an accelerator, this phase compresses significantly. The platform opinions are pre-made; you configure rather than build.
Phase 3: Service migration (2–6 weeks, depending on count)
Services migrate one at a time, starting with the least critical. Each service needs:
- A Dockerfile (often already exists)
- A Helm chart or Kubernetes manifests
- Resource requests and limits sized to actual usage
- Health check endpoints (liveness and readiness probes)
- Secrets sourced from the new secret management system
Once deployed, you run old and new in parallel, validate behavior, then cut traffic over. For stateless services, this is fast. For anything with state, it takes more care.
Phase 4: Database migration (1–2 weeks)
Databases are the hardest part of any migration. The goal is near-zero downtime, which typically means:
- Provisioning the new database (CloudNativePG for PostgreSQL is our recommendation for self-hosted)
- Setting up replication from the old database to the new one
- Running both in sync, validating data integrity
- Cutting the application over with a brief maintenance window or using logical replication for true zero-downtime
- Decommissioning the old database after a validation period
Don't underestimate this phase. It's where migrations go wrong.
Phase 5: Operations handover
After migration, the team running the cluster needs to actually know how to run it. This includes runbooks for common scenarios, alert tuning so the signal-to-noise ratio is useful, and enough cluster familiarity to handle a 2am incident without escalating.
For teams without prior Kubernetes experience, we recommend a structured handover period — not just documentation, but shared operations until the internal team has handled enough real situations to be confident.
What you shouldn't migrate to Kubernetes
A few honest caveats:
If your monthly PaaS spend is under $500 and your team is fewer than 2-3 engineers, Kubernetes is probably not the right move yet. The operational overhead, even reduced, is real. Stick with a PaaS and revisit when you've grown.
If your product is fundamentally a prototype or you're still searching for product-market fit, infrastructure stability should not be your focus. Kubernetes won't help you figure out if anyone wants your product.
If your entire engineering team is focused on product features and you have no one to own infrastructure decisions, Kubernetes without a partner is high risk. The platform is maintainable, but someone needs to own it.
The honest answer on "when to move"
The right time to consider this move is when at least two of these are true:
- You've had a PaaS-caused outage that affected paying customers
- Your monthly PaaS bill is above $500 and growing predictably
- You're trying to sell to enterprise customers with compliance or data residency requirements
- You're running more than 4-5 services and deployments are getting harder to coordinate
- Your team is investing significant time working around platform limitations rather than building product
If you're nodding at two or more of these, the conversation is worth having.
Kubernetes is the recommendation for teams that need the full combination of reliability, cost control, compliance support, and ecosystem maturity — and who are willing to invest in the transition.
Next Step
If you are interested, we'll look at your current setup, give you an honest assessment of whether migration makes sense, and — if it does — walk you through what it would actually take.
Book a 30-minute call with Anjul →
No pitch deck. No obligation. Just a direct conversation about your infrastructure and whether there's a better way to run it.
CloudRaft is a platform engineering and cloud consulting company working with companies in India and the US. We specialize in Kubernetes, observability, SRE/DevOps, and cloud infrastructure. Our Kubernetes consulting and platform engineering practices exist specifically for companies that have outgrown their current infrastructure.

