Hatchet: durable task orchestration with Postgres as the durability layer
🪓 An orchestration engine for background tasks, AI agents, and durable workflows
At a glance
- What is it?
- Hatchet is an MIT-licensed orchestration engine for background tasks, AI agents and durable workflows, written in Go with SDKs for Python, TypeScript, Go and Ruby. Its distinguishing decision is using Postgres for both the task runtime and the observability system, which is what makes self-hosting practical.
- Who is it for?
- Adopt Hatchet if you already operate Postgres and want durable execution, retries, rate limits and a monitoring UI without standing up a separate persistence stack. Do not adopt it if you need a durable execution engine with a long track record of production deployments at very large scale, or if you cannot run Docker locally to evaluate it.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem Hatchet targets: correctness for work that outlives a request
A background job that must survive a process restart, a third-party API that rate-limits you, a DAG where step four cannot start until steps one through three succeed: these are the cases Hatchet is built for. The README frames the target as systems where correctness, reliability, horizontal scalability and observability are essential, and the feature list follows that framing rather than trying to be a general-purpose message broker. The intended user is a backend or platform engineer who already has application code in Python, TypeScript, Go or Ruby and wants to move long-running or failure-prone work out of the request path without assembling a queue, a scheduler, a retry library, a metrics pipeline and a UI from separate parts. Hatchet ships those as one platform, available either as Hatchet Cloud or self-hosted.
Postgres as the durability layer, and what that changes
The README states the architectural difference plainly: Hatchet uses Postgres as a durability layer for both the task runtime and the observability system, which the project says makes it particularly easy to self-host. That single sentence has consequences worth spelling out. Durable execution normally requires a persistence component that records workflow state so a crashed worker can resume rather than restart, and a separate observability store for run history and logs. Collapsing both onto Postgres means a self-hosted deployment does not need a second stateful system, and the operational skills your team already has for Postgres apply. The trade-off is that the database becomes a shared dependency for scheduling, state and telemetry, so its availability and write throughput set the ceiling for the whole engine. The README does not publish sizing guidance, so how that behaves under a heavy telemetry load is something you would have to establish yourself. On top of that layer sit the primitives: background tasks defined as plain functions, retries with optional exponential backoff, cron and scheduled runs, event-based triggering with durable event waits, webhook triggers, and DAGs. Durable tasks handle long-running workflows that must recover from failure, and pause or resume is expressed through durable sleep, event waits, or both. The docs include a guide comparing durable tasks against DAGs, which is the decision most teams hit first.
Getting a local instance running with the Hatchet CLI
The README gives one path for local setup. You install the CLI on macOS, Linux or WSL, and Docker must be installed locally for it to work:
curl -fsSL https://install.hatchet.run/install.sh | bash hatchet --version hatchet server start
The version check is not decoration. It confirms the binary landed on your PATH before you ask it to start a server. Piping a remote script into bash is the documented install method, so if your environment requires checksum verification or a pinned release, you will need to fetch and inspect the script rather than run the one-liner as written. The README also recommends signing up for Hatchet Cloud even if you intend to self-host, on the grounds that it shows you what a fully deployed platform looks like. That is a reasonable way to see the monitoring UI and alerting before you commit to running them yourself, though it does mean the quickest evaluation path sends you through a hosted product. Full self-hosting documentation lives at docs.hatchet.run/self-hosting, and the README does not inline the production deployment steps. Worker-side configuration is documented separately: worker labels and worker affinity for routing, worker slots to cap how much work a single worker takes on, concurrency policies keyed on dynamic values for fair scheduling, and rate limits including per-user dynamic limits. Those are the keys you will spend real time on, because they determine whether your workers stay busy without overwhelming a downstream API.
Where Hatchet is the wrong tool
Hatchet is a workflow engine, not a general message bus. If your requirement is fan-out pub/sub with many independent consumers and no notion of run state, the durable execution machinery is overhead you will pay for and not use. The second constraint is the Postgres dependency. It is the reason self-hosting is approachable, but it also means you cannot run Hatchet without a Postgres instance you trust, and the engine's behaviour is coupled to that database's health. Teams standardized on another operational store should treat this as a real migration cost, not a detail. Third, the version numbers in the release feed are worth reading carefully: the core engine is at 0.106.5 while the Python SDK is at 1.40.1 and the Ruby SDK at 0.8.0. A pre-1.0 core version signals that interfaces can still move, and independently versioned SDKs mean server and client compatibility is something you verify rather than assume. The README does not state a compatibility matrix, so pin both sides and read the release notes before upgrading. Finally, the README's claim of being feature-complete is a claim about coverage, not about depth in every area. The docs are the place to check whether a specific primitive behaves the way your workload needs.
Temporal as the alternative, and the actual difference
Temporal is the obvious comparison for durable execution, and the difference is in where state lives and what you operate. Temporal's architecture separates the workflow history store from the visibility store, which is why running it yourself involves more than one stateful component; Hatchet's README explicitly positions Postgres as the durability layer for both the runtime and the observability system, and presents that as the reason self-hosting is easy. So the choice is less about feature lists than about operational surface: Hatchet asks you to run and scale Postgres, Temporal asks you to run its own persistence topology. Hatchet's SDK story is also broader in language terms than you might expect from a Go project, with Python, TypeScript, Go and Ruby all listed, while its event, webhook and cron triggering are presented as first-class rather than bolted on. What Hatchet does not offer in the supplied material is any evidence of production scale or longevity; the README makes no claims there, and you should not read the feature list as one. If your organization already runs Temporal and has operational familiarity with it, switching to Hatchet buys you a simpler storage story and costs you that familiarity. If you are starting fresh and Postgres is already in your stack, the calculation runs the other way.
Maintenance, upgrades and the MIT licence
The release cadence visible in the feed is frequent: Python SDK 1.40.1, core 0.106.5 and Ruby SDK 0.8.0 all landed within a few days of each other in September 2026. Frequent releases are good for fixes and bad for upgrade discipline, and with three independently versioned artifacts you have three things to track. The Ruby SDK sitting at 0.8.0 while Python is at 1.40.1 tells you the SDKs are not released in lockstep, so an upgrade plan that treats Hatchet as one version number will break. Pin the server image and each SDK, and read the release notes for the component you are bumping. On licensing, the repository is MIT, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are included. That is a permissive licence and it applies to the code in this repository. It does not automatically cover Hatchet Cloud, which is a separate hosted service with its own terms, nor does it settle questions about how you distribute modified versions inside a product. Those are questions for your own legal review; nothing here is legal advice. The practical maintenance cost is the Postgres instance you now depend on for both scheduling and telemetry, which means backup and capacity planning for that database are part of running Hatchet, not separate from it.
Who should adopt Hatchet, and what to verify first
The fit is a team with Postgres already in production, application code in one of the four supported languages, and a backlog of work that needs retries, scheduling and a visible run history. The self-hosting story is the strongest argument, because it collapses two stateful systems into one you likely already operate. The misfit is a team that needs a message bus, or one that cannot accept a pre-1.0 core dependency for work with strict availability requirements, or one without Docker available for local evaluation. Before you commit, do three things. Read the self-hosting documentation at docs.hatchet.run/self-hosting rather than relying on the CLI quickstart, since the README does not inline the production path. Run the local server with hatchet server start and exercise the specific primitives you depend on, particularly concurrency policies and rate limits, because those determine worker behaviour under load. Then pin your versions: 0.106.5 for the engine, 1.40.1 for the Python SDK, 0.8.0 for Ruby, and check the release notes for whichever component you upgrade next. The repository is the source of truth for the API surface; the README is a map of it, not a specification.
Editorial conclusion
Adopt Hatchet if you already operate Postgres and want durable execution, retries, rate limits and a monitoring UI without standing up a separate persistence stack. Do not adopt it if you need a durable execution engine with a long track record of production deployments at very large scale, or if you cannot run Docker locally to evaluate it. Before committing, verify three things in the repository itself: the self-hosting deployment path in the docs, the exact retry and concurrency semantics your workload depends on, and whether the SDK version you install matches the server version you run. The Python SDK is at 1.40.1, the Ruby SDK at 0.8.0 and the core at 0.106.5, so the client libraries are versioned independently of the engine and you should pin both.
Community notes