Skip to content
All posts

Not Every Deployment Problem Needs Kubernetes

June 29, 2026·Read on Medium·

Sometimes the mature answer is not the most advanced infrastructure. It is the simplest setup that safely fits the application, team and operating risk.

The deployment conversation that keeps repeating

I saw someone show how they deploy an application to a VPS on Tiktok.

The flow was familiar. SSH into the server, pull the latest code, install dependencies, build assets, run migrations, restart the process and check whether the application still responds.

Was it perfect? No.

Was it reckless by default? Also no.

It looked like the kind of deployment many small teams start with. It is direct, understandable and easy to reason about. The problem is not that the idea is completely wrong. The problem is that manual deployment tends to become risky when it is repeated often. One missed command can leave the application in a half-deployed state. One wrong branch can push the wrong code. One migration can run before the code that expects it. One restart can be forgotten. One person can become the only one who knows how production actually works.

So my first thought was simple.

This process needs more discipline.

Use a deploy script. Use Deployer. Use Laravel Forge. Use a managed VPS panel. Use GitHub Actions over SSH. Use a release-directory deployment pattern with a symlink switch. Add rollback. Add health checks. Add logs. Add backups. Make the boring process repeatable.

Then someone gave the classic answer. “Use Kubernetes”.

That is where I stumbled. Ah. Here we go again~

Not because Kubernetes is bad. Kubernetes is a serious piece of infrastructure. It solves real problems for real systems. The issue is that it has become a reflex answer in many technical discussions. Someone has a deployment problem, someone else recommends an orchestration platform. Someone has a messy VPS, someone says Kubernetes. Someone has one application, one database and a small team, someone says Kubernetes like it is the natural next step.

That is not always engineering maturity.

Sometimes that is just tool escalation.

Technically correct does not mean operationally appropriate

A recommendation can be technically valid and still be wrong for the situation.

Kubernetes can run the application. That does not mean the application needs Kubernetes.
A Lamborghini can drive to the market. That does not mean it is the right vehicle for buying vegetables.

The analogy is imperfect, but the point is useful. The question is not whether the tool is powerful. The question is whether the power solves the actual problem without creating a bigger one.

  • If the current problem is unreliable manual deployment, the first target should be repeatability.
  • If the current problem is no rollback, the first target should be a safer release strategy.
  • If the current problem is unknown server state, the first target should be provisioning discipline and documentation.
  • If the current problem is no visibility, the first target should be logs, metrics and alerts.
  • If the current problem is no backup, the first target should be backup and restore testing.

Kubernetes can exist inside a mature answer to those concerns, but it does not automatically replace those concerns. You still need deployment design. You still need environment management. You still need secrets discipline. You still need monitoring. You still need people who understand what happens when the system fails.

A bad deployment process inside Kubernetes is still a bad deployment process. It only has more moving parts.

The real problem was not orchestration

Many small deployment problems are not orchestration problems.

They are workflow problems.

A developer manually logs into production because there is no clean release path. That is a workflow problem.

A team does not know which version is running because deployments are not recorded. That is a workflow problem.

Queue workers keep running old code after deployment because nobody restarts them gracefully. That is a workflow problem.

Assets are built differently on each machine because the build is not standardized. That is a workflow problem.

The server works only because one senior developer remembers the correct command sequence. That is a workflow problem.

For those cases, the solution does not have to begin with a cluster. It can begin with one repeatable command. It can begin with a deploy script that everyone can read. It can begin with a tool like Deployer. It can begin with Laravel Forge deployment hooks. It can begin with GitHub Actions calling a locked-down SSH command. It can begin with the simplest thing that removes human memory from the release process.

That is not amateur. That is how maturity often starts.

The first professional step is not always distributed infrastructure. Sometimes the first professional step is making sure the same deployment steps run the same way every time.

Simple infrastructure can still be serious

There is a strange insecurity in software infrastructure discussions.

Some teams feel that a VPS is automatically junior. Some engineers feel that Nginx, Supervisor, a systemd service and a database backup plan sound less impressive than pods, services, ingress, operators and clusters. Some companies want to say they use Kubernetes because it sounds modern.

But simple infrastructure is not the same as careless infrastructure.

A single VPS can be operated badly. It can also be operated well.

A Kubernetes cluster can be operated well. It can also be operated badly.

The maturity is not in the label. The maturity is in the operational behavior.

Can you deploy without guessing?
Can you roll back when the release is bad?
Can you restart workers safely?
Can you recover the database?
Can you renew certificates?
Can you see errors before customers complain?
Can another engineer understand the setup?
Can you patch the server?
Can you explain why each moving part exists?

If the answer is yes, a VPS setup may be more professional than a cluster nobody understands.

For many Laravel applications, a boring VPS setup with Nginx, PHP-FPM, Redis, a managed database, Supervisor, scheduler, logs, backups and a release-based deployment process can carry a real business for a long time. It may not impress the cloud-native crowd, but the customer does not care whether the application runs on a cluster. The customer cares whether it is available, fast and safe enough for the job.

Kubernetes is an operating model, not a deploy button

The biggest mistake is treating Kubernetes as a deployment upgrade.

It is not only that.

Kubernetes changes the operating model.

Once a team chooses Kubernetes, it is not only choosing where containers run. It is choosing how applications are packaged, scheduled, scaled, exposed, configured, observed and recovered. It is choosing a different vocabulary. It is choosing manifests, images, registries, probes, resource limits, namespaces, ingress controllers, services, secrets and cluster upgrades.

That may be the right choice.

But it is a choice.

The official Kubernetes material describes capabilities like service discovery, load balancing, storage orchestration, automated rollouts and secret management. Those are powerful capabilities. They are valuable when a system needs them. They are not free just because the software is open source.

Someone has to understand the cluster.
Someone has to secure it.
Someone has to upgrade it.
Someone has to debug networking.
Someone has to manage persistent storage.
Someone has to decide resource requests and limits.
Someone has to configure logs and metrics.

Someone has to explain to the application team why a pod restarted, why traffic did not reach the service or why a rollout did not behave as expected.

For a team that already has platform capability, this can be normal. For a small team trying to ship one application, this can become a second product inside the product.

The cost of complexity is paid during incidents

Complexity is easy to add during planning.

It is paid back during incidents.

On a calm day, a Kubernetes diagram can look clean. Boxes connect to other boxes. Workloads restart. Traffic shifts. Deployments roll forward. Everything sounds controlled.

At 2 AM, the question changes.

Who knows why the pod is crash looping?
Who knows whether the issue is application code, image build, secret injection, resource pressure, ingress config, DNS, node health or database connectivity?
Who knows where logs are stored?
Who knows whether the last rollout can be safely undone?
Who knows whether a migration already ran?
Who knows whether the queue workers are processing the right version?

This is why infrastructure decisions should be made with incident handling in mind.

A simple system that the team understands is often safer than a powerful system the team treats like magic.

That does not mean avoiding sophisticated infrastructure forever. It means earning it. The team should grow into complexity when the application, traffic, service count, compliance need or organizational structure makes the complexity worthwhile.

There are better intermediate steps

The jump from manual VPS deployment to Kubernetes skips several useful levels.

Level 1 — manual deployment.

It is acceptable for experiments, demos and early internal tools, but it becomes risky when production matters.

Level 2 — script.

One command runs the steps. It is still simple, but it removes memory from the process.

Level 3 — deployment tool

Deployment tool such as Deployer. For PHP applications, this can add structure around releases, shared directories, framework recipes and rollback behavior.

Level 4 — managed VPS

Managed VPS workflow such as Laravel Forge. Forge gives teams a web interface for server management and application deployment. Its documentation covers deployments, deployment output, quick deploy, deploy scripts and zero downtime deployment strategy. For Laravel applications, it also has specific support around scheduler, Horizon, Octane and related runtime concerns.

Level 5 — CI-driven deployment

GitHub Actions, GitLab CI or another pipeline can build, test and trigger deployment from a controlled workflow. This gives the team traceability. It also reduces the habit of logging into production for normal releases.

Level si6— Docker Compose.

Compose is useful when the application has multiple containers and the team wants the stack described in one file. It can be especially helpful for development parity, staging environments and small server deployments where full orchestration is not required.

Level 7 — Kubernetes (MAYBE).

By the time a team reaches this point, the conversation is different. It is no longer about avoiding a manual pull on a VPS. It is about workload orchestration, scaling, service discovery, rollout control, resource scheduling and platform consistency.

This progression matters because it gives teams options.

The choice is not manual SSH or Kubernetes. There is a lot of engineering maturity between those two points.

When Kubernetes starts making sense

Kubernetes starts to make sense when the system has Kubernetes-shaped problems.

  • That might mean many services that need a consistent deployment model.
  • It might mean workloads that need horizontal scaling.
  • It might mean multiple teams shipping services onto a shared platform.
  • It might mean a company wants standard infrastructure primitives across applications.
  • It might mean service discovery, internal networking and rollout control have become real operational needs.
  • It might mean the organization already has people who can own the platform.
  • It might mean the business cost of downtime justifies more mature orchestration, automation and resilience work.
  • It might mean the deployment frequency, service count or infrastructure footprint has outgrown the simplicity of one or two servers.

In those situations, Kubernetes can be a strong answer. It gives teams a common control plane. It gives a way to describe desired state. It gives patterns for rolling updates, service exposure and self-healing workloads.

But that is different from saying every application should start there.

A tool becomes mature when it fits the problem. The same tool becomes wasteful when it is used to signal sophistication.

The Laravel example makes this obvious

Take a common Laravel application.

It has a web process, queue workers, a scheduler, Redis, a relational database, file storage, logs and maybe Horizon. It needs SSL, environment variables, deployment hooks, permissions, backups and monitoring.

A small team can run that well without Kubernetes.

  • They can use a VPS with Nginx and PHP-FPM.
  • They can use Supervisor or Forge-managed background processes for queues.
  • They can use the Laravel scheduler through cron or Forge scheduler configuration.
  • They can use a managed database instead of running the database on the same server.
  • They can use object storage for user uploads.
  • They can use Deployer or Forge zero downtime deployment to reduce release risk.
  • They can use Sentry, log shipping or another monitoring path to catch production errors.

They can keep the system understandable.

For many teams, that is already enough.

The trade-off is clear. Kubernetes may offer a more standardized orchestration layer, but it also asks the team to containerize the application, manage manifests, configure ingress, handle persistent concerns correctly, operate cluster components and understand a larger failure surface.

If the business only needs one or two Laravel applications to run reliably, the simpler setup may be the better engineering decision.

Not because Kubernetes cannot do it.

Because Kubernetes may solve more than the team needs to solve.

Overengineering often arrives dressed as best practice

This is the part many engineers do not like to admit.

Overengineering rarely announces itself as overengineering.

It usually arrives with good language.

  • Best practice.
  • Future proofing.
  • Cloud native.
  • Scalable architecture.
  • Production grade.

Those phrases are not automatically wrong. The problem is when they are used to skip the cost discussion.

Future proof for what future?
Scalable to what scale?
Production grade under whose operational ownership?
Best practice for which team size?

Cloud native because the business needs it or because the engineer wants the resume line?

Infrastructure decisions should not be made to win an argument in a comment section. They should be made against the reality of the product.

A five-person team with one monolith, modest traffic and no platform engineer does not have the same constraints as a company running hundreds of services across multiple teams. Giving both teams the same default answer is lazy advice.

The senior answer starts with context.

The better question to ask

When someone says use Kubernetes, the best response is not to reject it immediately.

The better response is to ask what problem Kubernetes is solving here.

Is the application failing because one server cannot handle traffic?
Is deployment unsafe because releases are manual?
Is rollback missing?
Are there many services?
Is there a need for self-healing workloads?
Is the team already containerizing applications?
Is there a platform team to operate the cluster?
Is the business willing to pay the complexity cost?

Will Kubernetes reduce operational risk or just move it somewhere less familiar?

These questions change the conversation.

They force the recommendation to connect with reality.

Sometimes the answers will support Kubernetes. Good. Use it.

Sometimes the answers will point to Deployer, Forge, Docker Compose, better scripts, better monitoring or a managed hosting platform. Also good. Use that.

The goal is not to defend a favorite tool. The goal is to choose the smallest reliable operating model that supports the current application and the next reasonable stage of growth.

Simple should not mean stagnant

There is one warning worth adding.

Do not use simplicity as an excuse for laziness.

A manual deployment process can be improved. A VPS can be hardened. A backup plan can be tested. A server can be documented. A deploy script can be reviewed. A rollback process can be practiced. A monitoring system can be added.

Simplicity should mean intentional design with fewer moving parts.

It should not mean undocumented servers, mystery commands, shared root passwords and hope.

A mature small setup still needs standards.

  • It needs source control.
  • It needs environment separation.
  • It needs limited access.
  • It needs reliable deployment.
  • It needs rollback.
  • It needs backups.
  • It needs alerting.
  • It needs ownership.

If those things are missing, the setup is not simple. It is fragile.

The right answer is not to jump to Kubernetes just to cover the fragility with more tooling. The right answer is to fix the operating discipline first.

The sentence I wish more engineers used

The industry would have better infrastructure discussions if more engineers used this sentence:

Kubernetes might be the answer, but first we need to know whether this is an orchestration problem, a deployment workflow problem or an operations discipline problem.

That sentence is less exciting than use Kubernetes.

It is also more useful.

It gives space for context. It respects the tool without worshipping it. It respects the small team without treating them as unserious. It keeps the discussion anchored to the actual failure mode.

Because that is the real work of senior engineering.

Not choosing the most advanced tool.

Not choosing the simplest tool blindly.

Choosing the tool whose complexity is justified by the risk it removes.

The closing position

I am not against Kubernetes. I am against using Kubernetes as a personality.

Kubernetes is powerful when the system needs orchestration. It is valuable when the team can operate it. It is sensible when the service count, scaling need, platform strategy or business risk justifies it.

But if someone is manually pulling code on a VPS, the first useful advice may be much smaller.

  • Create a repeatable deployment process.
  • Stop deploying by memory.
  • Add rollback.
  • Do separate releases.
  • Restart workers safely.
  • Track deployments.
  • Add monitoring.
  • Test backup and restore.
  • Use Deployer, Laravel Forge, CI deployment, Docker Compose or another tool that fits the current stage.

Then revisit Kubernetes when the problem has actually become a Kubernetes problem.

The goal of infrastructure is not to impress other engineers.

The goal is to run the application safely, recover when things break and keep the team productive.

Sometimes that means Kubernetes.

Sometimes that means a VPS, a good deployment workflow, clear ownership and enough operational discipline to sleep at night.

The senior decision is knowing the difference.

Found this helpful?

If this article saved you time or solved a problem, consider supporting — it helps keep the writing going.

Originally published on Medium.

View on Medium
Not Every Deployment Problem Needs Kubernetes — Hafiq Iqmal — Hafiq Iqmal