You want to build against Temporal on your own machine: a local server, the Web UI, and your worker connected to it. Here are the three ways to get there, fastest first, including the one where you don't set up anything at all.
Option 1: The Temporal CLI dev server
The quickest standalone route is the dev server built into the Temporal CLI:
# macOS
brew install temporal
# or any platform
curl -sSf https://temporal.download/cli.sh | shStart it:
temporal server start-devYou get a Temporal server on localhost:7233 and the Web UI on http://localhost:8233. Point your worker at localhost:7233 with no API key and you're running workflows in under a minute.
Two things to know:
- State is in-memory by default. Restart the process and every workflow, schedule, and namespace is gone. For persistence across restarts, pass a database file:
temporal server start-dev --db-filename temporal.db. - It's a dev server on purpose. Single process, SQLite-backed. Perfect locally, not something to expose or deploy.
Option 2: Docker Compose
For something closer to a production topology, Temporal maintains docker-compose configurations that run the full server against PostgreSQL, MySQL, or Cassandra, with optional Elasticsearch for visibility search:
git clone https://github.com/temporalio/docker-compose.git
cd docker-compose
docker compose upThis is the right choice when you specifically need to test against a production-like cluster, for example to exercise advanced visibility queries. For everyday development it's heavier than you need: slower to start, more moving parts, and you're now maintaining a compose file.
The part both options leave out
A local server is half the job. You still have to:
- Export
TEMPORAL_ADDRESSand friends in every shell (and make sure production points elsewhere). - Remember to start the server before your worker, or stare at
connection refusederrors. - Write it all down so the setup survives contact with a teammate's machine, or with your coding agent.
That glue is exactly what tends to rot.
Option 3: Zero setup with Specific
Specific treats Temporal as a first-class building block. You declare the engine in your project's specific.hcl and reference it from your services:
temporal "jobs" {}
service "worker" {
build = build.app
command = "node worker.js"
env = {
TEMPORAL_ADDRESS = temporal.jobs.url
TEMPORAL_NAMESPACE = temporal.jobs.namespace
TEMPORAL_API_KEY = temporal.jobs.api_key
}
}Then:
specific devOne command does all of it:
- Downloads the Temporal CLI automatically (first run only).
- Starts a dev server with persistent storage, so workflow state survives restarts without any flags.
- Serves the Temporal Web UI inside the local dashboard, next to your logs and database.
- Starts your worker with the env vars already resolved, in the right order.
There's nothing to install first and nothing to document for the next person: the config file is the setup. This also makes it the local Temporal story that works best with coding agents. Your agent edits specific.hcl, runs specific check to validate it, and specific dev to test the result end to end.
The same three references resolve to a managed Temporal Cloud namespace when you run specific deploy, so local and production run identical code. More on that in the Managed Temporal guide.
Troubleshooting local Temporal
connection refused on localhost:7233: your worker started before the server, or the server isn't running. With temporal server start-dev, start it in another terminal first. With specific dev, ordering is handled for you.
My workflows disappeared after a restart: you're running the dev server without persistence. Add --db-filename temporal.db, or use specific dev, which persists by default.
Port already in use: another dev server instance is still running. Find it with lsof -i :7233 and stop it, or start on different ports with --port and --ui-port.
Can the dev server run a small production deployment?
It comes up a lot: the dev server is one process, it's tiny, and it persists to SQLite when you ask it to. Why not run it for a small deployment?
Because Temporal says not to, and the reasons are structural rather than a matter of scale. From the CLI docs: "The development server is not intended for production use" and "it skips certain HTTP security checks to make local use simpler." On the storage side, Temporal lists SQLite as "meant only for development and testing, not production usage."
What that means in practice:
- One process, no redundancy. The four server services (frontend, history, matching, worker) run inside a single binary. If it stops, so does every workflow.
- No security layer. There is no authentication, no TLS between components, and the HTTP checks mentioned above are off. Anything that can reach the port can run workflows.
- Visibility doesn't scale. Workflow search runs on SQLite. Temporal recommends Elasticsearch or OpenSearch "for any setup that spawns more than a few Workflow Executions."
- No upgrade path. The dev server is whatever version of the CLI you installed. A production server is upgraded one minor version at a time, with schema migrations applied first; the dev server gives you none of that machinery.
Its resource footprint is small because it does so little. That is the point of it locally, and the reason it isn't a production server.
For a genuinely small deployment you have two honest options. Self-host a single-node Temporal Server against PostgreSQL (the docker-compose setup is that, more or less), accepting that you own upgrades, backups, and TLS. Or use a managed namespace, which is what we do: a temporal block in specific.hcl becomes a Temporal Cloud namespace on deploy, and the same worker code that ran against the dev server runs there unchanged. Self-hosting a real server is a longer list than most people expect, and we will cover it in a separate post.
Common questions
Which port does the Temporal dev server use?
gRPC on 7233 and the Web UI on 8233 by default (the UI port is the gRPC port plus 1000). Change them with --port and --ui-port. With specific dev, the port is allocated for you and exposed as temporal.<name>.url.
Does the dev server persist workflow state?
Not unless you tell it to. By default workflow executions are lost when the process dies. Pass --db-filename temporal.db to persist to SQLite. specific dev always persists, to a SQLite database under the project's .specific/ directory.
Can I run two dev servers at once?
Yes, on different ports: temporal server start-dev --port 7234 --ui-port 8234. With specific dev you don't need to: all temporal blocks in a project share one local dev server, each in its own namespace named after the block, and separate instances (for example one per git worktree) get their own port set.
How do I open the Web UI?
Standalone, go to http://localhost:8233. With specific dev, the Web UI is embedded in the local dashboard under Workflows, next to your services' logs and your database.
Next steps
- A complete working project with workflows, activities, and a worker: the durable workflows example (live demo, source).
- The full Temporal guide in our docs.
- New to the concept? Start with what durable execution is.
To try Specific, give your agent this prompt:
Help me get started with Specific by following: https://docs.specific.dev/for-ai/onboardingOr install the CLI directly:
curl -fsSL https://specific.dev/install.sh | sh