Tiger Style

Version 0.1-dev

This website outlines the core principles of Tiger Style, a coding philosophy focused on safety, performance, and developer experience. Inspired by the practices of TigerBeetle, it focuses on building robust, efficient, and maintainable software through disciplined engineering.

Summary

  1. Core principles
  2. Design goals
    1. Safety
    2. Performance
    3. Developer experience

Additional sections: Addendum, Colophon

1. Core principles

Tiger Style is not just a set of coding standards; it's a practical approach to software development. By prioritizing safety, performance, and developer experience, you create code that is reliable, efficient, and enjoyable to work with.

Safety

Safety is the foundation of Tiger Style. It means writing code that works in all situations and reduces the risk of errors. Focusing on safety makes your software reliable and trustworthy.

Performance

Performance is about using resources efficiently to deliver fast, responsive software. Prioritizing performance early helps you design systems that meet or exceed user expectations.

Developer experience

A good developer experience improves code quality and maintainability. Readable and easy-to-work-with code encourages collaboration and reduces errors, leading to a healthier codebase that stands the test of time [1].

2. Design goals

The design goals focus on building software that is safe, fast, and easy to maintain.

2.1. Safety

Safety in coding relies on clear, structured practices that prevent errors and strengthen the codebase. It's about writing code that works in all situations and catches problems early. By focusing on safety, you create reliable software that behaves predictably no matter where it runs.

Control and limits

Predictable control flow and bounded system resources are essential for safe execution.

Memory and types

Clear and consistent handling of memory and types is key to writing safe, portable code.

Error handling

Correct error handling keeps the system robust and reliable in all conditions.

2.2. Performance

Performance is about using resources efficiently to deliver fast, responsive software. Prioritizing performance early helps design systems that meet or exceed user expectations without unnecessary overhead.

Design for performance

Early design decisions have a significant impact on performance. Thoughtful planning helps avoid bottlenecks later.

Efficient resource use

Focus on optimizing the slowest resources, typically in this order:

  1. Network: Optimize data transfer and reduce latency.
  2. Disk: Improve I/O operations and manage storage efficiently.
  3. Memory: Use memory effectively to prevent leaks and overuse.
  4. CPU: Increase computational efficiency and reduce processing time.

Predictability

Writing predictable code improves performance by reducing CPU cache misses and optimizing branch prediction.

2.3. Developer experience

Improving the developer experience creates a more maintainable and collaborative codebase.

Name things

Get the nouns and verbs right. Great names capture what something is or does and create a clear, intuitive model. They show you understand the domain. Take time to find good names, where nouns and verbs fit together, making the whole greater than the sum of its parts.

Organize things

Organizing code well makes it easy to navigate, maintain, and extend. A logical structure reduces cognitive load, letting developers focus on solving problems instead of figuring out the code. Group related elements, and simplify interfaces to keep the codebase clean, scalable, and manageable as complexity grows.

Ensure consistency

Maintaining consistency in your code helps reduce errors and creates a stable foundation for the rest of the system.

Avoid off-by-one errors

Off-by-one errors often result from casual interactions between an index, a count, or a size. Treat these as distinct types, and apply clear rules when converting between them.

Code consistency and tooling

Consistency in code style and tools improves readability, reduces mental load, and makes working together easier.


Addendum

Addendum: Zero technical debt

While Tiger Style focuses on the core principles of safety, performance, and developer experience, these are reinforced by an underlying commitment to zero technical debt.

A zero technical debt policy is key to maintaining a healthy codebase and ensuring long-term productivity. Addressing potential issues proactively and building robust solutions from the start helps avoid debt that would slow future development.

Avoiding technical debt ensures that progress is true progress—solid, reliable, and built to last.

Addendum: Performance estimation

You should think about performance early in design. Napkin math is a helpful tool for this.

Napkin math uses simple calculations and rounded numbers to quickly estimate system performance and resource needs.

For example, if you're designing a system to store logs, you can estimate storage costs like this:

				
1. Estimate log volume:
   Assume 1,000 requests per second (RPS)
   Each log entry is about 1 KB

2. Calculate daily log volume:
   1,000 RPS * 86,400 seconds/day * 1 KB ≈ 86,400,000 KB/day ≈ 86.4 GB/day

3. Estimate monthly storage:
   86.4 GB/day * 30 days ≈ 2,592 GB/month

4. Estimate cost (using $0.02 per GB for blob storage):
   2,592 GB * 1000 GB/TB * $0.02/GB ≈ $51 per month
			

This gives you a rough idea of monthly storage costs. It helps you check if your logging plan works. The idea is to get within 10x of the right answer.

For more, see Simon Eskildsen's napkin math project.


Colophon

This document is a "remix" inspired by the original Tiger Style guide from the TigerBeetle project. In the spirit of Remix Culture, parts of this document are verbatim copies of the original work, while other sections have been rewritten or adapted to fit the goals of this version. This remix builds upon the principles outlined in the original document with a more general approach.