Tips for a better developer experience with Temporal

Tips for a better developer experience with Temporal

Symphony Logo
Symphony
July 21st, 2024

Temporal is a reliable runtime for polyglot, durable, and fault-tolerant applications. Its workflows, activities, schedules, and other abstractions do the heavy lifting, allowing you to focus on business code.

The gist of the story won't be about how Temporal works; for a high-level overview, go here: How it Works | Temporal Technologies

Temporal offers the critical benefits of resilience, durability, and observability, which are essential for projects. Aside from these benefits, Temporal is developer-friendly from the start. However, despite being developer-friendly, there are still pitfalls to avoid.

Here are some good tips for navigating Temporal pitfalls, leveraging its benefits, and easing development.

Create custom data transfer objects

Data sent through each activity needs to be serialized and deserialized. Hence, these objects should be lightweight and serializable. Avoid using big objects, as they can lead to errors.

Activities communicate back and forth with the Temporal server. Arguments flowing into activities need to be deserialized, and responses coming back from activities need to be serialized.

If you don't avoid this bad practice, you'll encounter this issue: "Complete result exceeds size limit". You can find the causes of this error on the Temporal Community support pages. 

The solution: store blobs instead of using them as activity payloads.

Activity and workflow payloads should be as small as possible. It's always better to return IDs rather than full-blown entity objects from activities. This way, we avoid serialization/deserialization overhead.

Wrap activity arguments into a single object

Activities and workflows are simple methods, meaning you can pass them an arbitrary number of arguments. However, if you don't use a wrapper for arguments, this will break backward compatibility as activities evolve. When there's one wrapper, you can easily change the data without changing the method arguments arity.

This approach is preferred:

669a751ce77862c7db258e93

Compared to this approach:

669a767ce77862c7db258fa1

This adds a bit of boilerplate, but the future benefits amortize it in the long run. While working with wrapped arguments, make sure they are serializable. All activity response and request properties need to be serializable.

669a73ade77862c7db258e0d

Retrying the above activity would execute each of the activity’s code lines multiple times, which could result in charging the customer multiple times. Breaking each line into a separate activity method will resolve the returnable issues.If indefinite retries are enabled per activity, the activity will retry until it succeeds or a non-retryable error occurs. This enables durable execution and appropriate action during execution. If the issue is resolved (the payment processor issue is resolved, and the charge is completed), the workflow is completed without intervention from customer support. This is especially helpful during downtime of a third-party service or when dealing with flaky services, as no failure occurs on the Temporal’s end at all.

669a741be77862c7db258e41

It's not so hard to notice the boilerplate. One must notice the boilerplate that becomes unmanageable at this point. This is one downside of the Temporal Java SDK. As you add more workflows and activities, you'll encounter more boilerplate.

Another downside is that each activity needs to be created as a new stub in each workflow. For example, this code:

669a744ae77862c7db258e53

Needs to be duplicated in every workflow that uses this activity.

Using Temporal judiciously will help reduce boilerplate.

Create custom search attributes to ease workflow filtering

Custom search attributes make the UI more digestible when you have many workflows. For example, a Temporal server could have this order of workflows in a development environment.

669a6cc8e77862c7db2586a0

Default search attributes can help filter this number down. Here are some default search attributes; the most helpful is ExecutionStatus.

669a7690e77862c7db258fb3

One custom search attribute that you could have is the ability to search by part of the workflow ID.

The default search attribute, workflowID, requires you to supply the full workflow ID in the query and doesn’t support partial search.

This is useful as you will most likely encode some identifiers within the workflow ID.

How to define custom search attributes?

Let's say we want to create a partial workflow ID search attribute. Here's the code to register the custom search attribute PartialWorfklowId on the Temporal service.

669a7472e77862c7db258e63

In the above example, the entire text is searchable by word. Other types can be used as index fields.

Closing words

In addition to these tips, Temporal provides many project samples to minimize the learning curve and improve developer experience.

The samples are available in all widely used languages (Java, Go, .NET), making it easy to learn and quickly prototype.

For Java developers, official Temporal server configuration support exists. You can use spring-boot-autoconfigure-alpha for Spring Boot projects. This library configures you so you don't have to register workflows and activities yourself.

Here is the code to register workflows from a single package automatically:

669a74a6e77862c7db258e73

All you need to do is annotate the relevant workflows and assign them to task queues.

Developer support, polyglot and developer-friendly guides, and easy setup make Temporal a strong contender for any developer's toolkit.

About author

Milos Zivkovic, an experienced Java Software Engineer from our Nis Branch at Symphony, has a background in integrating and developing secure, efficient, and scalable systems using Spring Boot, Temporal, and other modern technologies. He has worked on custom payment flows, custom authentication flows, and custom CI/CD pipelines. Milos aims to consistently deliver high-quality, business-aligned solutions while effectively communicating and implementing meaningful code improvements.

Contact us if you have any questions about our company or products.

We will try to provide an answer within a few days.