Why you should use immutable objects

Using immutable objects in your codebase has numerous benefits, especially when it comes to value objects. It makes your code easier to reason about, with less scope for side effects and subtle bugs. There are a few pitfalls to consider when designing immutable objects, and so using a 3rd party library to construct them can make your life much easier.

Read More

A Brief Summary of Retry Strategies

The goal of this post is to help you pick the right retry strategy for your use case. This will enable you to overcome transient API request failures, without causing wider system failure. We will first consider what happens with no retry strategy, compared with using a simple linear backoff strategy. Then we will see how adding jitter to the exponential backoff strategy can solve the thundering herd problem. Finally, we will solve the retry storm problem by using the token bucket retry condition.

Read More

Return nothing, with Java Optionals

In Java, it is common for a method to return null, or throw an exception, when it cannot return a value. In this post I aim to convince you to reach for the Optional class instead. This will make your code more readable, reliable and succinct.

Read More

Experimenting with AWS Lambda Cold Starts

AWS Lambda is a great serverless compute platform. It is extremely elastic, scaling up and down to meet your workload as required, so you only pay for the resources you actually need. However, as a consequence of this, it can suffer from slow function start up times: cold starts. In this post you will learn what you can do about this problem, especially in the context of Java applications. You will see how, with a few simple changes, cold start time can be halved, without an increase in costs. It can even be eliminated altogether, if you’re willing to accept some limitations.

Read More

Where to Log Exceptions

Logging exceptions that occur is important for understanding why a program, or part of it, failed. However, bad logging practices can make this debugging task needlessly difficult, with either missing information, or the same information repeated many times. In this post I discuss how to avoid these problems, and so quickly get to the root cause of issues.

Read More

AWS Lambda-SQS Integration - Scaling Surprises

Using SQS queues with Lambda functions is a very commonly used pattern, and for good reason. It’s a highly horizontally scalable way of processing messages, allowing services to stay decoupled from each other and scale independently. For convenience, back in 2018 AWS added SQS to the list of supported triggers for Lambda, allowing Lambda functions to automatically consume messages from SQS queues. However, some aspects of this integration don’t necessarily work how you might expect, which can lead to scaling issues if you’re not careful.

Read More

Fail-fast with Java's requireNonNull method

Null pointer exceptions can be a tricky bug because they can occur far from where the root cause of the problem is. A null value may be passed into one method, and that method may pass the argument on to another method, and so on. Then, when that value is finally used, an exception will be thrown. To debug the issue, you need to trace the source of the bad data through your program.

Read More