Our customers depend on the speed, reliability, and usability of Lob's API to send mission-critical mail like reimbursement checks. Another use is to make a memorable impression on a potential customer with a tailored postcard or letter. Lob generates thousands of physical, custom, irrevocable products on-demand every hour. We have to exceed the high bar of engineers that integrate our API into their stack. This starts with our engineering culture.
We operate with a discipline that most teams don’t adopt until much later. This discipline important to making our customers successful. Moreover, it demands the best from each engineer, which I find very stimulating and rewarding.
Everybody wants a great engineering culture but what that means is much harder to pinpoint. So here’s a look inside our engineering culture in practice.
Each substantial new engineering project is born from a need directly raised by our customers or identified by our sales and operations teams. From the outset, the problem is defined through close collaboration.
When it’s time to start a project, an engineer takes charge of researching the problem and proposing a written solution. The engineering team reviews the document, and meets in person for a deep dive. It takes passion and humility to sink your teeth into a problem and then open your work so others can make it better. There’s a saying we hear often about teamwork: “If you want to go fast, go alone. If you want to go far, go together.”
We would contend that mobilizing the entire team behind a plan is faster. Even if the lead engineer has to step aside, another engineer can step in without missing a beat.
Mention “support ticket” to a software engineer and you’ll often see a strange facial expression. At Lob we prioritize interacting with our customers, and our engineering team directly services technical support tickets.
We use a handful of APIs ourselves and know firsthand the value of a prompt, thorough, and technical reply. When each engineer is expected to support our customers first-hand, and expected to do it well, it keeps us close to the customer experience as we carry on our other responsibilities of building and maintaining products.
It’s perfectly normal to get anxious about drafting a response to a customer question, or hopping on a sales call to advise on an integration. We nudge each other forward and offer a second pair of eyes for a tricky response. In no time, our engineers become more comfortable interacting with customers. However, if an engineer is “too cool” to communicate with customers, they’re likely not a good fit for Lob.
Too often in software, we think of a first iteration as a solution that was just hacked together. But at Lob, we insist on first iterations being small and simple in scope, yet stable and easily extendable. You can never predict when your first iteration ends up picking up a lot of traction. While you don’t want to prematurely optimize, you can at least ensure you have a solid base.
Working in small but complete chunks allows us to experiment without burrowing technical debt throughout the codebase. We practice this principle by breaking up a project into smaller tasks in the sprint planning process and then circling back with a thorough code review process before any of them get merged into master.
It’s easy to let code reviews slip into a purely ceremonial exercise that provides the false sense of oversight but lacks the necessary diligence to be effective. At Lob, we review code throughout the day and most Pull Requests go through at least two rounds of revisions. It’s not enough for code to work, it has to be well-written and consistent with our style.
Standardized code enables new team members to easily grok and contribute across all of our repositories. It also causes bugs to stand out more because reviewers aren’t constantly trying to adjust to a different style from one author to another. To this end, we also limit pull requests to 300 lines changed—but when it can’t be avoided, we require a pair review of those bigger pull requests.
Sweating the details is the area that may take the most adjusting to when a new hire joins Lob, but it becomes second nature in no time. Plus, we’re always incorporating our new teammates’ ideas into our process. If you’re passionate about learning and growing as an active and central part of your job, the code review process is very satisfying.
Every line of code that is merged into master in any of Lob’s repositories must be accompanied by 100% test coverage. While this practice doesn’t abolish bugs, it does drastically reduce them. It also gives us the confidence to make substantial changes without harming existing functionality. We can sleep better at night because we’re not woken up by PagerDuty calls about critical bugs.
Without automated testing with significant coverage, quality control invariably falls to engineers manually testing at random. So if you can’t justify spending engineering time on writing tests, start by redirecting the time wasted by manual testing and you’ll see a much greater return. The test suites at Lob also serve as excellent living documentation of what each piece of code is expected to do.
Collaborative architecture, thorough code reviews, and 100% test coverage keeps us on our toes on a daily basis. So, on Fridays we balance it out by giving each engineer the day to work on experimenting with new technologies, contributing to open source, writing documentation, building internal tools, or tackling a pet project that isn’t on the sprint.
We’ve become more serious about carving out this time for ourselves and have already reaped the benefits. We used this time to revamp linting rules across our projects and even create custom rules. We built an automatic changelog generator based on git commits, and we created Calipers, the fastest way to measure file dimensions in Node.
If this sounds like a culture you’d like to be a part of and help shape, check out our current openings on the engineering team!