Tips and TricksLaravel CloudLaravel ForgeLaravel

August 15, 2026

How I Migrated Taskavel from Laravel Forge to Laravel Cloud

By Vladimir Nikolic

How I Migrated Taskavel from Laravel Forge to Laravel Cloud

How I Migrated Taskavel from Laravel Forge to Laravel Cloud

Forge served me well for years: it deploys from git, manages the VPS, runs cron and workers, and you always know exactly what is on the box. Laravel Cloud offers something different — fully managed infrastructure, no server to patch, managed queues that scale to zero, and zero-downtime deployments as a platform feature.

I recently moved Taskavel from Forge to Cloud, and this is the honest account of how it went — why I did it, what I got wrong, and the one trap I walked straight into that turned into a product of its own.

Two promises I will not make, because they would not be true: that the cutover is zero-downtime (plan for a window, be delighted if you do not need it), and that your bill will drop (it depends entirely on your traffic and usage — mine had a twist I will get to).

Why I moved

I did not move because Forge was failing me. I moved for two reasons.

Trust. I already host my own and my clients' applications on Laravel Cloud. Consolidating Taskavel onto the same platform I already rely on means one mental model, one dashboard, one place I know well.

Cost — in theory. Cloud can put an idle environment to sleep and stop charging for compute until the next request. For a product with quiet stretches, that is real money saved. (Keep that word "theory" in mind. It comes back to bite me later.)

On top of those: zero-downtime deployments, automatic managed-database backups, and priority support I already have on the platform. Enough to justify the move.

Suitability: is Laravel Cloud right for your app?

Before touching anything, be honest with yourself:

  • Do you want to keep doing server administration? If your team likes root on a box, Cloud takes that away. If patching, TLS renewal, and load-balancer config are chores you would rather outsource, Cloud does them for you.
  • Do you need server-level control? Cloud gives you application-level control — commands, background processes, environment variables — but no SSH. Any workflow that depends on installing system packages or poking at the filesystem needs redesigning first.
  • Are there hard constraints? Compliance rules, client requirements, or data-residency policies may rule out a managed platform or dictate a region.
  • What is your app's traffic shape? Cloud shines with spiky traffic — sleep when idle, autoscale during bursts. A steady, always-busy app gets less from elasticity.

The Cloud documentation is refreshingly clear about what the platform does and does not do. Read the compute and networking pages before you start, not after you hit a wall.

Inventory everything the server does

Forge has quietly been running a lot for you. The single most common migration failure is discovering a service you forgot to move. I will admit it: when I sat down to do this, I could not remember everything my Forge box was doing — which is exactly why you write it all down instead of trusting memory:

  • Web/PHP: PHP version (php -v — Cloud supports PHP 8.2 through 8.5, so older versions need an upgrade plan first), nginx tweaks, redirects, custom headers.
  • Cron jobs: crontab -l plus any Forge-scheduled jobs. Not just schedule:run — the manual scripts, backups, and cleanup jobs nobody remembers adding.
  • Queue workers: Supervisor configs, how many processes, which queues, and whether you use Horizon.
  • Redis: which caches are used, and what would be expensive to rebuild.
  • Storage: local disk files (uploads, exports) vs. S3/Spaces buckets.
  • Websockets: if you run Reverb or another server, note the port, auth, and config.
  • Email: mail driver (Mailgun, Postmark, SES, SMTP), and whether provider DNS is tied to the server.
  • Anything else: custom daemons, background scripts, offsite backups, firewall rules, certificate renewals Forge handles for you.

Every row maps to a Cloud feature (managed queue, scheduled task, object storage) or needs an explicit decision. That mapping becomes your migration checklist.

Databases and files: the two big moves

Database. The honest way is a controlled dump and restore: mysqldump (or pg_dump) from the current server, restored into a Cloud-managed database. Do it against a staging Cloud environment first — restore, run php artisan migrate against the copy, and compare row counts and spot-check records. Check one thing early: if you run on SQLite anywhere, Cloud does not support it — convert to MySQL/Postgres before the migration, not during it. (Cloud even has a MySQL-to-Postgres guide if you are switching engines too.)

Files. If uploads live on the server's disk, they must move to durable storage — Cloud compute is ephemeral, and anything written to local disk can disappear on redeploy. Provision an object-storage bucket and copy the files over with aws s3 sync, or use Cloud's read-through fallback disk so files migrate lazily on first access. Then switch FILESYSTEM_DISK. Test uploads and downloads on staging before cutover. If you were already on S3/Spaces, this is the easy part — point the same bucket at Cloud.

Environment variables and secrets: where I actually lost time

Your Forge .env is the source of truth; your Cloud environment is a fresh copy. Go through it line by line — and budget more time here than you think:

  • APP_KEY, APP_ENV, APP_URL — set for the new environment, and never reuse staging values in production.
  • Database credentials — new values for the managed database.
  • Third-party API keys (payments, mail, analytics) — move as-is unless you are rotating them.
  • Cache/session driver config if you are moving to Cloud's managed Valkey/Redis.
  • Use Cloud's secrets feature for anything sensitive, and never commit it.

This is the part that actually bit me. A few honest war stories:

  • Passport keys would not paste. Multi-line values (an RSA private key) simply would not go into the dashboard field cleanly. I ended up injecting the variables through the Cloud API instead — which, credit where due, is genuinely excellent and turned an annoyance into a two-minute scripted fix. If you have multi-line secrets, plan to use the API or CLI from the start.
  • Pricing and product IDs changed. Moving was a natural checkpoint to update our plan pricing and payment product IDs — do not blindly copy these across.
  • Dead values. I had .env keys for features we had already removed from Taskavel because nobody used them. A migration is a great moment to delete what you no longer run instead of faithfully carrying junk to a new home.

Cloud gives you separate environments per app, plus preview environments per pull request — so you can build staging with the same variable names (production values left blank) and keep production secrets out of it.

Build and runtime differences

The biggest mental shift: you no longer have a box. Cloud builds your app in a clean environment on every deploy — Composer and npm install from scratch, assets compile, the release swaps in. Consequences to plan for:

  • No SSH, no interactive prompts. Anything expecting a shell or an interactive command must become a non-interactive command run from the dashboard or API. Commands that prompt for confirmation will fail — there is a knowledge-base article about exactly this.
  • Build environment is not runtime environment. The npm run build that works on your laptop may behave differently in Cloud's build. Deploy to a preview/staging environment early to catch version mismatches.
  • No persistent local disk. Worth repeating: any write to local storage is temporary — session files, caches, generated files all belong on managed services.
  • Custom domains are set up in the dashboard, with automatic TLS.

Queues and the scheduler

Two Forge staples — Supervisor and cron — have managed equivalents, and they behave differently enough to test early.

Queues. On Cloud you have two honest paths:

  • Managed queues. Cloud provisions the queue, runs dedicated workers that autoscale (including down to zero), gives you a built-in failed-jobs dashboard, and — importantly — keeps processing even while your environment is asleep. Your app dispatches over QUEUE_CONNECTION=cloud.
  • Self-managed workers. You run php artisan queue:work yourself as a background process on an app or worker cluster, using whatever driver you like. This is the closer analog to a Forge setup. If you want Horizon, this is the only path it fits: Horizon monitors the redis connection and runs as a background process here — it does not sit on top of managed queues. It is one model or the other, not both.

For Taskavel I kept it deliberately boring: the database queue driver, worker running as a background process. No Valkey, no Horizon, no managed queues. Taskavel's job volume simply does not need them, and fewer moving parts meant fewer things to verify during the cutover. Pick the simplest thing that fits your load — you can always graduate to managed queues later. (One caveat if you lean on scale-to-zero: a self-managed worker can be interrupted when the environment sleeps mid-job, which is exactly why Cloud recommends managed queues for apps that sleep. Taskavel never sleeps — more on that in a second — so this never bit me.)

Scheduler. Forge's cron entry for schedule:run becomes Cloud's scheduled tasks setting — enable it on your compute and confirm schedule:list matches what ran on the server. Then run both old and new schedules for a few days and diff what actually fired.

Websockets (Reverb or similar) run as background processes on compute — document the port and the broadcasting config change before cutover.

The trap I walked straight into: my app never sleeps

Here is the part I am slightly embarrassed about, and the part you will learn the most from.

One of my two reasons for moving was cost, via scale-to-zero: Cloud puts an idle environment to sleep and stops charging for compute until the next request. Money saved. On paper.

Then I deployed the dev environment and watched it flatly refuse to sleep. Taskavel sends reminders, and the scheduler fires every single minute. Cloud wakes a sleeping environment to run scheduled tasks, and each wake keeps it awake for the full sleep timeout — which the next minute's task promptly resets. A minute-level schedule means the environment is effectively awake forever. The scale-to-zero savings I migrated for quietly evaporated.

I solved it — but the solution grew into its own product and deserves its own post, which is coming soon, and it is where wakeavel.com comes in. For now the lesson stands on its own: scale-to-zero only saves money if your app can actually sleep. Audit your schedule before you bank on the savings.

DNS, cutover, and rollback

The cutover is the only part your users see, and it is the part you can rehearse.

  1. Build and validate on Cloud first. Get staging fully working: deploy, migrate, exercise queues, cron, uploads, and email.
  2. Pre-stage production. Create the production environment, deploy, set up a temporary URL, and run smoke tests against it directly.
  3. Choose your moment. If your app tolerates a maintenance window, switch DNS during it. If you want a seamless cutover, sequence the steps (database first, then DNS) so the old server never writes data the new one will not see. For many apps, a short maintenance window is the honest way to get this right.
  4. Flip DNS (lower the TTL beforehand), verify TLS, verify the domain.
  5. Keep Forge running as a standby. I kept the Forge server up until I flipped DNS, and left it running afterward. Cloud keeps previous deployments so you can roll back the app itself, and the old server is your fallback for platform-level problems. Keep it at least a week, then decommission deliberately after final backups.

Monitoring

Before you switch DNS, get eyes on the new environment:

  • Logs: Cloud's logs view for application and access logs.
  • Metrics: CPU/memory via compute metrics.
  • Errors: keep your existing tracking (Sentry, Flare, Nightwatch) pointed at the new environment and watch for new exceptions in the first days.
  • Uptime and alerts: external uptime checks on the production domain, and a spending limit with alerts so a "managed" platform cannot surprise you on the bill.

Cost and operations tradeoffs

Let me be straight about the economics, because marketing copy will not be.

Forge pricing is simple: a flat per-server fee plus your VPS bill. Cloud bills on usage — compute, databases, queues, bandwidth. A low-traffic app that genuinely sleeps can cost less; a busy app, or one that never sleeps (ask me how I know), can cost more. Model it with your actual numbers, and check your schedule before you count on scale-to-zero.

The operations trade is control for convenience. You lose SSH and server-level customization; you gain automatic TLS, managed-database backups, one-click rollbacks, and no patching duty. For a small team without a dedicated ops person, that trade is usually worth it. For a team that lives in the server, it is a real loss of capability. Decide with your workload, not the brochure.

Post-migration validation

The migration is not done when DNS points at Cloud; it is done when the old server has been quiet for a week. In the days after:

  • Daily flows: logins, registrations, password resets (email delivery!), uploads/downloads, payments and webhooks.
  • Workers: confirm jobs are processing and nothing is silently dropped.
  • Scheduler: confirm scheduled jobs ran on time.
  • Caches: connectivity, and few cache misses after warmup.
  • Rollback drill: trigger a rollback on staging to confirm it actually works — knowing how is not the same as having done it.
  • Decommission: after the standby period, take final backups from the old server, then shut it down.

Where Coding Wisely comes in

Migrating platforms is a great moment to have someone who has done it before. At Coding Wisely we help with the inventory, the database and file moves, the queue and cron rework, the cutover sequence, and the post-migration validation — and we will tell you honestly when staying on Forge is the better call for your app. If you are weighing the move or already mid-migration, get in touch.

Frequently Asked Questions

Will the migration have zero downtime? I would not promise that, and neither should you. Laravel Cloud deploys with zero-downtime releases, but the migration itself involves databases, files, DNS, and a change of platform. Plan a maintenance window, sequence the data moves carefully, and treat a seamless cutover as a pleasant surprise, not a requirement.

Will Laravel Cloud cost less than Forge + VPS? Not necessarily. Forge is a flat fee plus your VPS; Cloud bills on usage. Low-traffic apps that genuinely sleep can be cheaper; always-busy apps can cost more. And watch your scheduler — a task that fires every minute keeps the environment awake around the clock and erases scale-to-zero savings entirely. That one surprised me on Taskavel.

Do I need to change my application code? Mostly configuration, not rewrites: filesystem disk, queue/cache driver, environment variables. The common exceptions are apps that write to local disk (move to object storage), run on SQLite (convert to MySQL/Postgres first), or depend on SSH-level access.

What happens to my Forge server? Keep it as a standby through cutover and for at least a week after. Once the new environment is stable and validated, take final backups and decommission deliberately.

What about cron jobs I set up directly on the server? They do not move automatically. Inventory crontab -l and every Forge scheduled job, map each to a Cloud scheduled task or command, and run both schedules side by side for a few days to confirm nothing was missed.

Can I use Horizon on Laravel Cloud? It is one model or the other, not both. If you use Cloud's managed queues, you dispatch over the cloud connection and monitor jobs in Cloud's own failed-jobs dashboard — Horizon is not in the picture. If you want Horizon, run your own queue:work on an app or worker cluster against a Valkey/Redis cache and run Horizon as a background process there. Managed queues are the lower-maintenance default; Horizon is the choice when you want its dashboard and control. (For Taskavel I used neither — just the database driver, which is plenty for its volume.)

Are you set to create something extraordinary?

Ready to take the next step? Let's work together to transform your ideas into reality. Contact us today to discuss how we can help you create impactful, user-centered solutions that drive success.

Contact Us