Skip to content

Why Temporal?

Impetus

Coordinating a transaction across systems and databases has long been talked about in literature. The first paper on sagas came out of Princeton in 1987. A textbook from the same year, Concurrency Control and Recovery in Database Systems, discussed implementations of Two-Phase Commit. Since then, these ideas have been iterated, innovated, and repackaged several times.

Temporal is a framework for orchestrating these workflows in a durable sense. It grew out of Uber (then known as Cadence) and was pivotal in allowing them to orchestrate long-running business logic processes.

Quick references

Before you dive in…

Check these resources out

Hear from Temporal folks directly.
Quick Intro Series B Slides
Why Temporal? Blog Post from Swyx
Temporal in 2 Minutes Short YouTube video
Temporal in 7 Minutes Short YouTube video
Intro to Temporal with Go SDK 35 minute YouTube video
samples-go Code reference of a workflow from the samples-go repo
money-transfer Code reference of a workflow from the money-transfer example

Past Experience

Distributed systems have never been easier (and, paradoxically, maybe harder) to build. In past roles, I saw systems built to varying degrees of success. I’ve seen engineers not concern themselves with data consistency issues, dismissing them as “edge cases”.

“Just Use a Goroutine”

“Let’s just wrap this function in a Goroutine. It’s a distributed system. Boom. Done.” By 2019, in my professional career of only a few years, I had encountered this line of thinking more than once.

Go offers such convenient and powerful concurrency primitives, that you can’t really blame folks for thinking this way. This is definitely the feeling you get from reading this errgroup article, or from watching Sameer’s coffee-shop talk, where he shows how to model a real-world concurrent system in Go.

So I had seen folks implement these kinds of “inter-process communication” scenarios in one of two ways:

package main
func myRequestHandler() {
txn := db.StartTransaction()
// perform some DB updates
txn.Commit()
sendEvent()
}

The Transactional Outbox pattern solves the edge cases. It may feel like “over-engineering” to some, but in reality it’s a good engineering practice.

Infrastructure Proliferation

By 2021, I had heard of “Sagas”, but had never used them in my professional career. Instead, what I had seen time and time again, was microservices choreography with message brokers like Kafka.

Conceptually, choreography is sound. It’s even decentralized, which is all the hype considering the ascendence of Web3. In practice, however, it’s quite expensive in terms of development and infrastructure.

The images from Swyx’s blog are real problems faced by large enterprises, which are so big and flushed with so much cash that it’s more convenient to have bad design proliferate than it is to make a good one.

../../../assets/swyx.webp

And if proliferation and duplication of DevOps-type work isn’t the problem on such a giant scale, then it might be on a smaller scale. Even small shops use some combination of glued-together databases, queues, and schedulers.

Enter Temporal

There needs to be some libary/mechanism/platform/etc for orchestrating “long-lived” workflows. Whether that’s Temporal or something else is irrelevant. Having a code-native developer experience for solving these challenges has compounding advantages in the long run, which is why so many companies have adopted Temporal.