Lombok: Shortcut or Technical Debt? Lessons from a Year of Using Java Boilerplate Reduction
After a year of using Project Lombok, the author reflects on its initial appeal for reducing Java boilerplate, then reveals how hidden technical debt, version incompatibilities, reduced readability, and increased coupling can outweigh its benefits, urging teams to weigh its adoption carefully.
If you are reading this article, you probably already have some familiarity with Project Lombok. Are you ready to embrace Lombok, or are you considering recommending this cool library to your team? Before you decide, consider the author's reflections after a year of using Lombok.
Lombok is a useful Java library that lets you write less code while looking cool; a few simple annotations can eliminate a large amount of boilerplate. However, most source code is read, and only a little is executed .
One year ago, like most people, I believed Lombok would improve the Java coding experience and strongly recommended it to my team. After a year, I began to have concerns, especially when upgrading the Java version of the open‑source blog system Una‑Boot. I realized Lombok had fallen into a trick trap. Analyzing its source code and understanding the annotations, I found I did not need a non‑standard third‑party library to make Java code look sleek. Introducing Lombok gave a short‑term thrill, but the price was accumulating technical debt as the project progressed.
The Beginning of Love, the Origin of Hate
When you see the many "magic moves" Lombok offers, you won’t mind adding a plugin to your IDE. For IntelliJ IDEA users, just search for "Lombok Plugin" and install it. Falling in love with Lombok starts with installing the plugin, and the hate begins from there.
Before using Lombok, a typical JavaBean looks like this:
<code>public class MyObject {
private Long id;
private String name;
private int age;
private int gender;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public int getGender() { return gender; }
public void setGender(int gender) { this.gender = gender; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyObject obj = (MyObject) o;
return age == obj.age && gender == obj.gender &&
Objects.equals(id, obj.id) && Objects.equals(name, obj.name);
}
@Override
public int hashCode() { return Objects.hash(id, name, age, gender); }
@Override
public String toString() {
return "MyObject{" + "id=" + id + ", name=" + name + ", age=" + age + ", gender=" + gender + "}";
}
}
</code>Every JavaBean is filled with such getter, setter, equals, hashCode, and toString boilerplate, making the code look "fat". After installing the Lombok plugin, the IDE recognizes the annotations and the code becomes much slimmer:
<code>@Getter
@Setter
public class MyObject {
private Long id;
private String name;
private int age;
private int gender;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyObject obj = (MyObject) o;
return age == obj.age && gender == obj.gender &&
Objects.equals(id, obj.id) && Objects.equals(name, obj.name);
}
@Override
public int hashCode() { return Objects.hash(id, name, age, gender); }
@Override
public String toString() {
return "MyObject{" + "id=" + id + ", name=" + name + ", age=" + age + ", gender=" + gender + "}";
}
}
</code>You might think Lombok can only do this, but it can make your code even slimmer. By adding
@EqualsAndHashCode, the equals and hashCode methods are generated automatically:
<code>@Getter
@Setter
@EqualsAndHashCode
public class MyObject {
private Long id;
private String name;
private int age;
private int gender;
@Override
public String toString() {
return "MyObject{" + "id=" + id + ", name=" + name + ", age=" + age + ", gender=" + gender + "}";
}
}
</code>Now the code looks much cleaner, but we can go further. Adding
@ToStringremoves the need for a manual toString method:
<code>@Getter
@Setter
@EqualsAndHashCode
@ToString
public class MyObject {
private Long id;
private String name;
private int age;
private int gender;
}
</code>Finally, Lombok provides a composite annotation
@Datathat replaces all the above annotations with a single line:
<code>@Data
public class MyObject {
private Long id;
private String name;
private int age;
private int gender;
}
</code>Beyond these, Lombok offers other annotations such as
@Slf4j,
@NoArgsConstructor,
@AllArgsConstructor, etc., but they are not the focus of this article.
Distorted Aesthetics, Hidden Risks
Using Lombok makes the code look sleek, but it also puts the code into an "sub‑healthy" state. Remember the earlier statement: All source code is mostly read, and only a little is executed.
In principle, we aim to reduce boilerplate to make code more concise and maintainable. Lombok achieves this by injecting methods at compile time, which is a clever trick but not intelligent or safe. It can break existing Java features and hurt readability. Below are the main pain points observed after using Lombok.
1. JDK Version Issues
When upgrading a project from Java 8 to Java 11, Lombok stopped working. I had to remove all Lombok annotations and let the IDE generate getters, setters, equals, hashCode, toString, and constructors, or use the Delombok tool. This consumes a lot of time.
2. Forced Adoption
If your code uses Lombok, anyone who depends on your code must also install the Lombok plugin and understand its annotations; otherwise the code will not compile. This feels intrusive.
3. Poor Readability
Lombok hides the details of JavaBean encapsulation. For example,
@AllArgsConstructorgenerates a massive constructor that allows external code to set every field, which can be unsafe. With many fields, the generated constructor has dozens of parameters in an order controlled by Lombok, making debugging difficult. Before running the code, you can only imagine what the methods look like.
4. Increased Code Coupling
When a module uses Lombok, all dependent modules must also include Lombok as a dependency and install the plugin. This invasive coupling can become disastrous when combined with JDK version problems.
5. Cost vs Benefit
Lombok feels great at first, but it pollutes the code, harms Java’s integrity, readability, and safety, and adds technical debt. If you want concise code while preserving readability and efficiency, consider using mainstream JVM languages such as Scala or Kotlin.
Conclusion
Lombok is an excellent Java library that provides syntactic sugar to simplify code and reduce boilerplate. However, it is not a standard Java library. Using Lombok increases team technical debt, reduces code readability, and raises coupling and debugging difficulty. While it reduces boilerplate, it also introduces unknown risks. If you are working on a team or large project, discuss carefully with your team before deciding whether to adopt Lombok.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.