You Don't Need Kubernetes for Your Laravel App | Deploynix Laravel Blog
Back to Blog

You Don't Need Kubernetes for Your Laravel App

Sameh Elhawary · · 14 min read
You Don't Need Kubernetes for Your Laravel App

In January 2026, another "we moved off Kubernetes" post hit the front page of Hacker News. The details were familiar: a team of eight engineers spending roughly 60 hours per week maintaining their Kubernetes setup before finally replacing it with Docker Compose on plain servers. Sixty hours. That's one and a half full-time engineers doing nothing but keeping the orchestrator happy, for a product that could run on three machines.

The comments followed the usual script. Half the thread said "you were doing it wrong." The other half said "we did the same thing and got our weekends back." Both halves are right, and that's the interesting part.

This post makes a specific claim: if you're running a Laravel application, you almost certainly don't need Kubernetes, and the reasons are stronger for Laravel than for most stacks. I'll be fair about what Kubernetes actually solves, honest about what it costs, and specific about the boring architecture that covers 95% of Laravel apps in production. And I'll tell you when you genuinely do need k8s, because some readers do.

The pattern keeps repeating

The "we left Kubernetes" essay is a genre now, and it sits inside a bigger trend. A Barclays CIO survey found that 86% of CIOs plan to move some workloads back from the public cloud, and we've unpacked the whole repatriation trend separately.

Repatriation and de-Kubernetesing aren't the same thing, but they share a root cause. Teams adopted complexity designed for a scale they never reached, paid the tax for years, and eventually did the math.

Here's what strikes me about the HN thread and every post like it: the teams involved aren't incompetent. They're usually good engineers who adopted Kubernetes for defensible reasons. Résumés, hiring pipelines, "we might need to scale," a consultant's recommendation, or a genuine belief that this is just how modern infrastructure works. The problem isn't the engineers. The problem is a mismatch between the tool and the workload.

So let's define the workload Kubernetes was built for, and then look honestly at whether your Laravel app resembles it.

What Kubernetes actually solves

It's easy to write a smug takedown of Kubernetes. It's more useful to be precise about what it's genuinely good at, because that precision is exactly what tells you whether you need it.

Bin-packing many heterogeneous services. If you run 40 different services with wildly different resource profiles, some CPU-hungry, some memory-hungry, some spiky, Kubernetes will pack them onto a fleet of nodes far more efficiently than a human assigning services to servers in a spreadsheet. At that scale, the scheduler pays for itself in hardware savings alone.

Org-scale multi-team platforms. When 15 teams each ship their own services, you need namespaces, resource quotas, RBAC, admission controllers, and a standard deploy interface so teams don't step on each other. Kubernetes is the industry's answer to "how do 200 engineers share a compute platform without a meeting for every deploy." That's a real problem, and k8s solves it well.

True elastic scaling. If your traffic genuinely swings 10x within minutes, ticketing on-sales, viral consumer apps, ad-driven spikes, then horizontal pod autoscaling plus cluster autoscaling can absorb it without a human touching anything. Provisioning a new VPS by hand doesn't compete with that.

Self-healing across nodes. A node dies at 3 a.m., and the workloads on it get rescheduled elsewhere before your monitoring even pages you. If you run enough machines that node failure is a weekly event rather than a yearly one, this matters a lot.

These are real capabilities. Kubernetes won the orchestration war because it does these four things better than anything else. Now, the uncomfortable question.

Does your Laravel app have any of these problems?

Walk through the list again with a typical Laravel application in mind.

Heterogeneous services to bin-pack? No. You have one codebase. Your "services" are the same application in different modes: PHP-FPM serving web requests, Horizon running queue workers, the scheduler firing cron entries, maybe Reverb for WebSockets. They share the same code, the same vendor directory, the same deploy artifact. There's nothing to bin-pack. A scheduler optimizing placement across a heterogeneous fleet has no work to do when the fleet is three identical app servers.

Multi-team platform needs? Almost certainly not. Most Laravel teams are 1 to 10 developers shipping one application. You don't need namespaces and RBAC to stop teams colliding when there's one team. The coordination problem Kubernetes solves at the org level simply doesn't exist for you.

Elastic 10x traffic swings? Be honest about your traffic graph. Most Laravel apps, SaaS products, internal tools, e-commerce, client platforms, have daily and weekly rhythms you can predict a month out. Your Tuesday looks like last Tuesday. When growth comes, it comes over weeks, which is plenty of time to resize a server or add one. In our experience, teams that think they need autoscaling usually need a correctly sized server and a queue.

Node failure at fleet scale? With 2 or 3 servers, hardware failure is a rare event, and a load balancer health check plus a spare app server handles it. You don't need a control plane rescheduling pods across a cluster; you need the LB to stop sending traffic to a dead box, which Nginx and every cloud load balancer has done since before Kubernetes existed.

There's a deeper point here about Laravel specifically. The framework's entire production story was designed for boring servers. PHP-FPM's process model is its own worker pool manager. Horizon supervises, balances, and auto-scales queue workers within a machine, with a dashboard, out of the box. The scheduler collapses all your cron jobs into a single crontab entry. Octane exists for when you want to squeeze more requests out of the same hardware. Laravel already ships the 20% of orchestration you actually need, at the application layer, where you can debug it with dd() instead of kubectl describe.

Kubernetes solves problems Laravel apps don't have, using abstractions Laravel already provides simpler versions of.

What Kubernetes costs you

The costs are the half of the equation that adoption decisions consistently underweight. They come in four flavors.

The stack tax

Kubernetes is never just Kubernetes. To run a production Laravel app on it you'll assemble, at minimum: Helm charts or Kustomize overlays for templating, an ingress controller, cert-manager for TLS, an image registry and build pipeline, a secrets story (sealed-secrets, external-secrets, or a vault), and an observability stack because your logs are now scattered across ephemeral pods. Each piece has versions, upgrade cycles, breaking changes, and its own GitHub issues page you'll come to know well.

Compare the artifact counts. A Laravel deploy on a plain server is an Nginx vhost, a Supervisor config, and a crontab line. The same app on Kubernetes means a deployment, service, ingress, HPA, ConfigMap, and secret manifest per component, plus the chart plumbing that templates them. Every one of those files is code you maintain and can misconfigure.

The money

Managed control planes bill you for the privilege of the abstraction, and the worker nodes still cost the same as the VPSes you'd have used anyway. Meanwhile the boring option keeps getting cheaper: a 4 GB Hetzner CPX-class server runs about €7.99/month, versus $24/month for the equivalent DigitalOcean droplet, and Hetzner egress is around €1.19/TB against $10/TB at DO and roughly $90/TB at AWS. A three-server Laravel setup can cost less per month than the observability add-ons on a typical cluster.

The hiring bar

Once Kubernetes is load-bearing, every infrastructure hire needs to know it, or you need to train them. You've raised the bar for a role that used to be "comfortable with Linux and Nginx." The HN team's 60 hours per week is the extreme case, but even a well-run small cluster quietly consumes a day or two of engineering time per week in upgrades, chart bumps, certificate mysteries, and CVE responses. That time comes directly out of product work.

The debugging tax

This one hurts the most at 2 a.m. On a plain server, a misbehaving Laravel app is a tail -f on the log, a supervisorctl status, maybe an strace if things get weird. On Kubernetes, the same investigation traverses ingress, service, endpoint, pod, container runtime, and overlay network before you reach your code. Each layer is a place the problem can hide and a place your mental model can be wrong. Abstraction layers are cheap on the whiteboard and expensive in an incident.

The boring architecture that covers 95% of Laravel apps

What does a typical Laravel app actually need? Three stages, and none of them involve YAML.

Stage 1: one good VPS

One server running Nginx, PHP-FPM, Horizon, MySQL, and Valkey. That's the whole diagram. A 4 vCPU / 8 GB machine handles more traffic than most developers expect; a well-tuned single server comfortably serves the workloads of the vast majority of production Laravel apps.

The moving parts are almost embarrassingly simple. Horizon runs under Supervisor:

[program:horizon]
process_name=%(program_name)s
command=php /var/www/app/current/artisan horizon
autostart=true
autorestart=true
user=deploy
stopwaitsecs=3600
stdout_logfile=/var/www/app/shared/storage/logs/horizon.log

The scheduler is one crontab line:

* * * * * cd /var/www/app/current && php artisan schedule:run >> /dev/null 2>&1

That's your orchestration layer. Supervisor restarts Horizon if it dies. Cron fires the scheduler. Nginx and PHP-FPM have been serving PHP reliably since before containers were a product category.

Stage 2: split the database

When MySQL and PHP-FPM start competing for memory, move the database to its own server and point DB_HOST at its private IP. Two servers, one firewall rule, done. This single move buys most apps years of headroom, and I've written about the decision criteria in detail in Building a Multi-Server Laravel Architecture.

Stage 3: multiple app servers behind a load balancer

When one app server isn't enough, add identical app servers behind a load balancer, keep sessions and cache in Valkey, move user uploads to S3-compatible storage, and dedicate one server to Horizon and the scheduler so jobs and cron entries run exactly once (or chain ->onOneServer() onto scheduled tasks if the scheduler runs on every box). Three to five servers on this pattern will carry you a very long way; the full progression is mapped out in Scaling Laravel from 1 to 100,000 Users.

Notice what happened: you scaled from one server to a small fleet and never once needed a control plane, a service mesh, or a Helm chart. Each stage was an afternoon of work, and every piece is debuggable with tools you already know.

Every Kubernetes selling point, translated

The strongest argument for Kubernetes is a list of features that sound essential. Here's the same list next to what the boring stack has been doing for years.

Kubernetes gives you

The boring equivalent

Notes

Rolling deployments

Atomic symlink deploys

New release built alongside the old one, symlink swap, instant rollback. See The Anatomy of a Zero-Downtime Deploy

Liveness probes + pod restarts

Supervisor/systemd autorestart + monitoring alerts

Supervisor restarts a dead Horizon in seconds; alerts tell you it happened

Secrets objects

.env outside the web root, plus Laravel's encrypted env files

Simpler threat model, and no etcd to secure

Horizontal pod autoscaling

Add a VPS behind the load balancer

Takes minutes with predictable traffic; you'll see growth coming weeks out

Service discovery + DNS

Private IPs in your .env

You have three servers. You know their addresses

Ingress + cert-manager

Nginx + Let's Encrypt

One vhost file and a certbot renewal timer

ConfigMaps

Config files, deployed with your code

They're already versioned in Git

The pattern in every row is the same: Kubernetes generalizes a problem to N services across M nodes, and pays for that generality in complexity. When N is 1 and M is 3, the specific solution wins on every axis that matters, including reliability, because there's so much less to break.

Rolling deploys deserve one more sentence, since they're the feature people cite most. The releases-plus-symlink pattern gives you zero-downtime deploys and one-command rollbacks with ln -sfn. It's not a lesser version of what Kubernetes does. For a single application, it's the same guarantee with two orders of magnitude less machinery.

When you genuinely do need Kubernetes

If everything above described your situation, you can skip this section. But some readers are shaking their heads, and some of them are right to. Kubernetes earns its keep when:

  • You run dozens of genuinely distinct services. Not one Laravel app in three modes, but 30+ separately deployed services in multiple languages with different resource profiles. Now bin-packing and a uniform deploy interface pay real dividends.

  • You have a platform engineering team. If multiple product teams ship independently and someone's full-time job is the internal platform, Kubernetes is a reasonable substrate. The 60 hours per week stops being overhead and becomes the job description.

  • Your traffic is truly unpredictable at 10x scale. If a tweet or a TV spot can multiply your load in minutes and you can't eat the cost of permanent over-provisioning, cluster autoscaling solves a problem the boring stack handles awkwardly.

  • You already have deep k8s expertise in-house. Familiarity changes the math. A team that has run clusters for years pays a fraction of the learning-curve tax, and consistency with existing infrastructure has value.

If two or more of those apply, use Kubernetes with a clear conscience. The point of this essay isn't that k8s is bad. It's that the trigger for adopting it should be one of these conditions actually existing, not the possibility that one might exist someday. You can adopt Kubernetes in the quarter you need it. Adopting it three years early means paying the tax the whole time.

The middle ground

Between raw Kubernetes and hand-managed servers there's a spectrum, and it's worth knowing where the sane points are.

Docker Compose on a VPS. This is where the HN team landed, and it's a reasonable spot: you keep containerized builds and a declarative service definition, and drop the control plane entirely. The trade-off is that you're now managing Docker networking, image builds, and volume mounts for a stack (Nginx, FPM, MySQL) that installs perfectly well as native packages. For Laravel specifically, containers solve a dependency-isolation problem that PHP mostly doesn't have.

Managed platforms. Laravel Cloud (and, historically, Vapor) moves you up an abstraction level instead of down. You trade infrastructure control for zero maintenance, at a price that scales with usage. A fair option if usage-based billing fits your revenue model and you're comfortable not owning the box.

The boring stack, automated. This is the position Deploynix occupies, so weigh my bias accordingly. The architecture in this post, provisioned Nginx and PHP-FPM, Horizon under Supervisor, atomic symlink deploys with one-click rollback, Let's Encrypt, MySQL with automated backups, and server monitoring with alerts, is exactly what Deploynix sets up on a VPS from Hetzner, DigitalOcean, Vultr, Linode, AWS, or any server you can SSH into. You get the operational conveniences people adopt Kubernetes for (repeatable provisioning, safe deploys, restarts, alerts) without the cluster underneath. Flat pricing from free to $39/month, and no control plane to babysit.

The common thread across all three: each one is somebody deciding which slice of Kubernetes's value they actually need and buying only that slice.

The bottom line

The recurring "we left Kubernetes" post isn't a fad or a skill issue. It's teams discovering, one at a time, that they adopted a tool built for Google-shaped problems to run a workload shaped nothing like Google. A team of eight spending 60 hours a week on cluster maintenance is an extreme data point, but the direction of the error is common: complexity adopted years before, or instead of, the problem it solves.

Laravel makes the decision easier than most stacks. FPM manages your web workers. Horizon manages your queue workers. The scheduler manages your cron. Symlinks give you zero-downtime deploys. The framework already contains the orchestration a single application needs, which means Kubernetes has remarkably little left to offer until you're operating at genuine multi-service, multi-team scale.

So start boring: one good VPS. Split the database when memory pressure says so. Add app servers behind a load balancer when traffic says so. Reach for Kubernetes when, and only when, you can point at one of the four conditions above and say "that's us, today." Your future self, awake at 2 a.m. reading a plain log file instead of spelunking through pod events, will thank you.

Ready to deploy your Laravel app?

Deploynix handles server provisioning, zero-downtime deployments, SSL, and monitoring — so you can focus on building.

Get Started Free No credit card required

Related Posts