Mastodon Skip to main content
Available for Projects

I'm always excited to take on new projects and collaborate with innovative minds.

DevOps

Distributed Background Processing: Scaling Temporal Workflows with Laravel

Standard queues fail when background tasks last days or require complex state machines. Here is how to integrate Temporal workflows into your Laravel application.

Michael K. Laweh
2026-05-07 10:45:00 9 min read
Distributed Background Processing: Scaling Temporal Workflows with Laravel

Laravel's queue system is excellent. Redis-backed queues and supervisors can handle millions of standard jobs efficiently. However, when background processing evolves into complex, multi-day, retry-sensitive state machines, standard queues begin to show limits.

Consider a multi-step user onboarding flow:

  1. Send a welcome email.
  2. Wait 3 days.
  3. Check if the user uploaded a profile picture.
  4. If not, send a reminder.
  5. Wait another 4 days.
  6. If still incomplete, flag the account for manual sales outreach.

Implementing this with standard Laravel jobs requires writing complex database state tracking, configuring multiple delayed dispatch loops, and managing manual retry intervals. If a server reboots mid-process, tracking which step a user was on becomes an operational nightmare.

Temporal solves this. It is a workflow orchestration engine that guarantees state progression. It allows you to write standard PHP code while Temporal handles state persistence, timeouts, queryable statuses, and complex retries.

Here is how to integrate Temporal into your Laravel application.


1. Core Architecture: Workflows vs. Activities

Temporal separates execution logic into two concepts:

  • Workflows: The orchestrator. Workflows must be deterministic. They dictate the flow of execution, handle sleep intervals, and coordinate steps. Because they are deterministic, they must not interact directly with external systems, databases, or random functions.
  • Activities: The execution layer. Activities can be non-deterministic. They perform the actual work: making database queries, querying third-party APIs, sending emails, or writing files.

2. Setting Up Temporal in Laravel

To communicate with a Temporal cluster, install the official Temporal PHP SDK:

composer require temporal/sdk

Next, configure your Temporal environment. In your .env, define the location of your Temporal address (by default, a local installation runs on port 7233):

TEMPORAL_ADDRESS=127.0.0.1:7233

3. Writing Your First Workflow and Activity

Let’s implement the user onboarding flow described earlier.

Step 1: Define the Activity Interface and Implementation

Activities contain your standard Laravel logic, such as Eloquent database queries and mailing services.

namespace App\Temporal\Activities;

use Temporal\Activity\ActivityInterface;
use Temporal\Activity\Method\ActivityMethod;

#[ActivityInterface]
interface OnboardingActivitiesInterface
{
    #[ActivityMethod]
    public function sendWelcomeEmail(int $userId): void;

    #[ActivityMethod]
    public function checkProfileStatus(int $userId): bool;

    #[ActivityMethod]
    public function sendProfileReminder(int $userId): void;
}

Now, implement the activities using Laravel’s dependency injection:

namespace App\Temporal\Activities;

use App\Models\User;
use App\Mail\WelcomeMail;
use App\Mail\ReminderMail;
use Illuminate\Support\Facades\Mail;

class OnboardingActivities implements OnboardingActivitiesInterface
{
    public function sendWelcomeEmail(int $userId): void
    {
        $user = User::findOrFail($userId);
        Mail::to($user->email)->send(new WelcomeMail($user));
    }

    public function checkProfileStatus(int $userId): bool
    {
        $user = User::findOrFail($userId);
        return !empty($user->avatar_path);
    }

    public function sendProfileReminder(int $userId): void
    {
        $user = User::findOrFail($userId);
        Mail::to($user->email)->send(new ReminderMail($user));
    }
}

Step 2: Define the Workflow Interface and Implementation

The workflow dictates the timing and business logic. It orchestrates the activities.

namespace App\Temporal\Workflows;

use Temporal\Workflow\WorkflowInterface;
use Temporal\Workflow\WorkflowMethod;

#[WorkflowInterface]
interface OnboardingWorkflowInterface
{
    #[WorkflowMethod]
    public function runOnboarding(int $userId);
}

Implement the workflow, utilizing Temporal’s built-in time mechanics:

namespace App\Temporal\Workflows;

use Carbon\CarbonInterval;
use Temporal\Workflow;
use App\Temporal\Activities\OnboardingActivitiesInterface;

class OnboardingWorkflow implements OnboardingWorkflowInterface
{
    private $activities;

    public function __construct()
    {
        // Bind the activities interface with retry settings
        $this->activities = Workflow::newActivityStub(
            OnboardingActivitiesInterface::class,
            Workflow\ActivityOptions::new()
                ->withStartToCloseTimeout(CarbonInterval::seconds(30))
        );
    }

    public function runOnboarding(int $userId)
    {
        // 1. Send welcome email immediately
        yield $this->activities->sendWelcomeEmail($userId);

        // 2. Sleep for 3 days
        yield Workflow::timer(CarbonInterval::days(3));

        // 3. Check if they uploaded an avatar
        $hasUploadedAvatar = yield $this->activities->checkProfileStatus($userId);

        if (!$hasUploadedAvatar) {
            // 4. Send reminder email
            yield $this->activities->sendProfileReminder($userId);
        }
    }
}

4. Booting the PHP Worker

Unlike standard Laravel queues which run via artisan queue:work, Temporal requires a worker daemon to boot, register your workflows and activities, and poll the Temporal server for tasks.

Create an Artisan command app/Console/Commands/TemporalWorker.php:

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Temporal\WorkerFactory;
use App\Temporal\Workflows\OnboardingWorkflow;
use App\Temporal\Activities\OnboardingActivities;

class TemporalWorker extends Command
{
    protected $signature = 'temporal:work';
    protected $description = 'Start the Temporal PHP worker';

    public function handle(): void
    {
        $this->info("Starting Temporal PHP Worker...");

        $factory = WorkerFactory::create();
        $worker = $factory->newWorker('onboarding-task-queue');

        // Register implementations
        $worker->registerWorkflowTypes(OnboardingWorkflow::class);
        $worker->registerActivityImplementations(new OnboardingActivities());

        $factory->run();
    }
}

Keep this worker running in production using a process manager like Supervisor.


5. Dispatching the Workflow

To trigger the onboarding process (for instance, when a user registers), dispatch the workflow from your Laravel Controller or Event Listener:

namespace App\Http\Controllers;

use Temporal\Client\WorkflowClientInterface;
use App\Temporal\Workflows\OnboardingWorkflowInterface;

class AuthController extends Controller
{
    public function register(WorkflowClientInterface $workflowClient)
    {
        // Create user registration record...
        $user = Auth::user();

        // Start onboarding workflow asynchronously
        $run = $workflowClient->start(
            $workflowClient->newWorkflowStub(OnboardingWorkflowInterface::class)
        );

        $workflowClient->start($run, $user->id);

        return response()->json(['message' => 'Registration complete.']);
    }
}

Conclusion

Temporal shifts the complexity of managing background state machines away from your application database. By separating timing orchestration (workflows) from operational code (activities), you build highly readable, fault-tolerant background systems that scale reliably.

If you are looking to design complex distributed backends, migrate legacy cron structures, or scale transaction-sensitive workflows, let's connect.

Discuss your backend architecture with me.

Michael K. Laweh
Michael K. Laweh
Author

Senior IT Consultant & Digital Solutions Architect with 16+ years of engineering experience. Founder of LAWEITECH, builder of ScrybaSMS, Nexus Retail OS, and 4 open-source packages on Packagist. Currently building the next generation of AI-integrated enterprise tools.

Have a project in mind?

From AI-integrated platforms to enterprise infrastructure, I architect solutions that deliver measurable business results. Let's talk.

Post Details
Read Time 9 min read
Published 2026-05-07 10:45:00
Category DevOps
Author Michael K. Laweh
Share Article

Related Articles

View All Posts
Jun 04, 2026 • 10 min read
Debugging Postiz & Temporal: A Production Runbook for Self-Hosted Social Media Orchestration

Self-hosting your social media scheduler sounds easy until Temporal wo...

Apr 23, 2026 • 9 min read
Moving Off PaaS: Deploying Production Laravel Stacks with Kamal 2

PaaS costs scale faster than your user base. Kamal 2 allows you to dep...

Mar 16, 2026 • 8 min read
How I Finally Conquered Deployment Hell: The PHP Deployment Kit

Stop rewriting the same deployment tasks. Discover how I engineered a...