Back to Blog
Tutorial11 min read2026-07-02

How to Deploy a Temporal Workflow Application

Temporal makes distributed workflows durable and reliable, but deploying workers correctly takes care. This guide covers connecting to Temporal Cloud or self-hosted, deploying workers, and scaling them.

Ajay Kumar
Ajay Kumar
Founder & DevOps, PandaStack

Temporal turns flaky, multi-step processes — payment flows, order fulfillment, AI agent pipelines — into durable workflows that survive crashes and resume exactly where they left off. The programming model is elegant, but the deployment model trips people up because the *worker* is the thing you deploy, not a web server.

This guide deploys Temporal workers in production and connects them to either Temporal Cloud or a self-hosted cluster.

How Temporal deployment actually works

The key mental shift: your code runs in workers, which are long-lived processes that poll the Temporal service for tasks. There's no inbound HTTP. The architecture:

Your app (starts workflows) ─► Temporal Service ◄─ Worker(s) poll & execute
                                  (cluster or Cloud)

You deploy:

  1. 1Worker(s) — host your workflow + activity code, poll task queues.
  2. 2Optionally a starter / API — an HTTP service that kicks off workflows via the SDK client.
  3. 3The Temporal service — either Temporal Cloud (managed) or self-hosted.

Step 1: Write a worker

A minimal Python worker (the pattern is identical across Go/Java/TS SDKs):

# worker.py
import asyncio, os
from temporalio.client import Client, TLSConfig
from temporalio.worker import Worker
from workflows import GreetingWorkflow
from activities import compose_greeting

async def main():
    tls = None
    if os.environ.get("TEMPORAL_TLS_CERT"):
        tls = TLSConfig(
            client_cert=open(os.environ["TEMPORAL_TLS_CERT"], "rb").read(),
            client_private_key=open(os.environ["TEMPORAL_TLS_KEY"], "rb").read(),
        )
    client = await Client.connect(
        os.environ["TEMPORAL_ADDRESS"],
        namespace=os.environ.get("TEMPORAL_NAMESPACE", "default"),
        tls=tls,
    )
    worker = Worker(
        client,
        task_queue="greeting-tasks",
        workflows=[GreetingWorkflow],
        activities=[compose_greeting],
    )
    await worker.run()

asyncio.run(main())

Step 2: Containerize

FROM python:3.12-slim
WORKDIR /app
ENV PYTHONUNBUFFERED=1
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "worker.py"]
# requirements.txt
temporalio==1.7.0

Step 3: Choose your Temporal backend

Option A: Temporal Cloud (recommended to start)

Temporal Cloud is managed and handles the hard parts (persistence, history retention, scaling the service). You connect with mTLS or API keys. Set:

TEMPORAL_ADDRESS=<your-namespace>.<account>.tmprl.cloud:7233
TEMPORAL_NAMESPACE=<your-namespace>
TEMPORAL_TLS_CERT=/run/secrets/client.pem
TEMPORAL_TLS_KEY=/run/secrets/client.key

Store the cert/key as secret env vars or mounted secrets — never bake them into the image.

Option B: Self-host the Temporal service

Temporal's server needs a persistence store (Cassandra, MySQL, or PostgreSQL) plus optional Elasticsearch for advanced visibility. This is heavier to operate. If you go this route:

  • Provision a managed PostgreSQL for persistence.
  • Deploy the Temporal server container pointed at that database.
  • Point your workers at the server's gRPC endpoint (:7233).

For most teams, Temporal Cloud + self-hosted *workers* is the sweet spot: you own the cheap-to-scale part (workers) and let Temporal run the stateful part.

Step 4: Deploy the worker

  1. 1Push the worker repo to GitHub.
  2. 2Create a container app on [PandaStack](https://dashboard.pandastack.io) from the Dockerfile.
  3. 3Set the connection env vars and secrets.
  4. 4Deploy. Because workers have no inbound HTTP, you don't need a public port — this is a pure background service.

Important: do not put scale-to-zero on a worker. A worker that scales to zero stops polling and your workflows stall. Keep at least one replica always running. Free-tier scale-to-zero is designed for request-driven web apps, not pollers.

Step 5: Scale workers

Workers scale horizontally — add replicas to process more concurrent tasks. Tune SDK-level concurrency too:

worker = Worker(
    client,
    task_queue="greeting-tasks",
    workflows=[GreetingWorkflow],
    activities=[compose_greeting],
    max_concurrent_activities=100,
    max_concurrent_workflow_tasks=100,
)
LeverEffect
More replicasMore parallel task execution, fault tolerance
max_concurrent_activitiesPer-worker activity parallelism
Separate task queuesIsolate noisy workloads (e.g. heavy ML activities)
Dedicated worker per queueIndependent scaling for different job types

Step 6: Versioning and safe deploys

Workflows are long-running, so a code change mid-execution can break determinism. Use Temporal's [worker versioning / patching](https://docs.temporal.io/develop/python/versioning) so in-flight workflows finish on old logic while new ones use the new code. Roll out workers gradually rather than replacing all replicas at once.

Deploying the starter API (optional)

If you trigger workflows from a web request, deploy a small FastAPI/Express service that uses the Temporal client to call start_workflow. This *does* expose HTTP and can use normal autoscaling:

await client.start_workflow(
    GreetingWorkflow.run, "World",
    id="greeting-123", task_queue="greeting-tasks",
)

References

  • [Temporal documentation](https://docs.temporal.io/)
  • [Temporal worker concepts](https://docs.temporal.io/workers)
  • [Temporal Cloud](https://docs.temporal.io/cloud)
  • [Self-hosting Temporal](https://docs.temporal.io/self-hosted-guide)
  • [Temporal Python SDK](https://github.com/temporalio/sdk-python)

---

The cleanest Temporal setup is managed service + self-hosted workers, and workers are exactly the kind of always-on container PandaStack runs well. Pair them with a managed PostgreSQL if you self-host the cluster. Try it on the free tier at [dashboard.pandastack.io](https://dashboard.pandastack.io).

Ready to deploy?

Start free on PandaStack.

Start free on PandaStack

More in Tutorial

Browse all Tutorial articles →

See also