Skip to content
edgesync Documentation
Login

Documentation


name: tigerstyle

description: Use when writing safety-critical code, systems programming, infrastructure, or when a project needs rigorous coding discipline. Triggers include requests for defensive coding, assertion-heavy development, performance-conscious design, zero-technical-debt policy, or NASA Power of Ten style rules. Also use when reviewing code for correctness, safety, or performance issues.

TigerStyle

Adapted from TigerBeetle's coding style. Language-agnostic principles for writing safe, performant, maintainable code.

Design Priority

Safety > Performance > Developer Experience. All three matter. This order breaks ties.

Zero Technical Debt

Do it right the first time. Ship less, but ship solid. What we have meets our design goals. The second chance may never come.

A problem solved in design is 10x cheaper than in implementation, 100x cheaper than in production.

Safety Rules (adapted from NASA Power of Ten)

Control Flow

Bounds

Assertions

Assertions detect programmer errors (not operating errors). The only correct response to corrupt logic is to crash. Assertions downgrade catastrophic correctness bugs into liveness bugs.

Rule Example
Assert pre/postconditions and invariants Validate arguments at function entry
Minimum 2 assertions per function Check inputs AND outputs/state
Pair assertions — same property, two code paths Assert before write AND after read
Split compound assertions assert(a); assert(b); not assert(a && b)
Assert positive AND negative space Check what you expect AND what you don't
Assert compile-time constants Verify relationships between config values
Use assertions as documentation A true assertion > a comment, when the condition is critical

Language adaptation:

// Go: use explicit checks that panic on programmer error
func processBlob(data []byte, maxSize int) {
    if len(data) == 0 { panic("processBlob: data must not be empty") }
    if maxSize <= 0   { panic("processBlob: maxSize must be positive") }
    // ... logic ...
    if result < 0 { panic("processBlob: result must not be negative") }
}
// Rust: debug_assert for dev, assert for invariants that must hold in release
fn process_blob(data: &[u8], max_size: usize) {
    assert!(!data.is_empty(), "data must not be empty");
    assert!(max_size > 0, "max_size must be positive");
    debug_assert!(max_size <= MAX_BLOB_SIZE);
}
// TypeScript: throw for programmer errors at system boundaries
function processBlob(data: Uint8Array, maxSize: number): void {
    if (data.length === 0) throw new Error("processBlob: data must not be empty");
    if (maxSize <= 0) throw new Error("processBlob: maxSize must be positive");
}

Memory & Resources

Error Handling

Functions

External Events

Performance Rules

Design-Phase Thinking

The best time to solve performance — the 1000x wins — is in design, precisely when you can't measure.

Batching

Control Plane vs Data Plane

Be Explicit

Developer Experience Rules

Naming

Principle Good Bad
Descriptive, no abbreviations connection_timeout_ms conn_to
Units/qualifiers last, descending significance latency_ms_max max_latency_ms
Related names same length source / target src / dest
Nouns over participles for identifiers replica.pipeline replica.preparing
Helper prefixed with caller name read_sector_callback on_read_done
Callbacks last in parameter list fn read(path, opts, cb) fn read(cb, path, opts)

Comments

Variables & State

Division Intent

Dependencies

Formatting

Commit Messages

Quick Reference: Applying TigerStyle to Your Project

digraph tigerstyle_apply {
    rankdir=TB;
    "New code to write" [shape=doublecircle];
    "Design first?" [shape=diamond];
    "Back-of-envelope sketch" [shape=box];
    "Write assertions first" [shape=box];
    "Write implementation" [shape=box];
    "Check: >70 lines?" [shape=diamond];
    "Split function" [shape=box];
    "All errors handled?" [shape=diamond];
    "Add error handling" [shape=box];
    "Review naming + comments" [shape=box];
    "Done" [shape=doublecircle];

    "New code to write" -> "Design first?";
    "Design first?" -> "Back-of-envelope sketch" [label="yes"];
    "Design first?" -> "Write assertions first" [label="simple"];
    "Back-of-envelope sketch" -> "Write assertions first";
    "Write assertions first" -> "Write implementation";
    "Write implementation" -> "Check: >70 lines?";
    "Check: >70 lines?" -> "Split function" [label="yes"];
    "Check: >70 lines?" -> "All errors handled?" [label="no"];
    "Split function" -> "All errors handled?";
    "All errors handled?" -> "Add error handling" [label="no"];
    "All errors handled?" -> "Review naming + comments" [label="yes"];
    "Add error handling" -> "Review naming + comments";
    "Review naming + comments" -> "Done";
}

Adapting to Your Language

TigerStyle Rule Go Rust TypeScript Python
Assertions if cond { panic() } assert! / debug_assert! throw new Error() assert / raise
Explicit types Native (strongly typed) Native Strict TypeScript Type hints + mypy
Static allocation Pre-sized slices, sync.Pool Vec::with_capacity, arena Pre-allocated buffers Pre-sized lists, __slots__
Formatter gofmt rustfmt prettier black / ruff
Compiler strictness go vet, staticcheck clippy, deny warnings strict: true, noUncheckedIndexedAccess mypy --strict, ruff
Error handling Check every err ? operator, no unwrap in prod Try/catch at boundaries Explicit exception handling
No recursion Iterative with stack Iterative with stack Iterative with stack Iterative with stack

Common Mistakes

Mistake TigerStyle Fix
"I'll add assertions later" Assertions FIRST. They define the contract.
"This function is complex but it works" If it exceeds 70 lines, split it. Art is born of constraints.
"We can refactor later" Zero technical debt. Do it right now.
"The error can't happen here" Assert it can't. If you're wrong, you'll know immediately.
"Performance can be optimized later" Design for performance. The 1000x wins are in design, not profiling.
"The variable name is obvious in context" It won't be obvious in 6 months. Be descriptive. Add units.
"Let's add this dependency, it saves time" Every dependency is a liability. Can you write the 50 lines yourself?

The Essence

"Simplicity and elegance are unpopular because they require hard work and discipline to achieve." — Dijkstra

Simplicity is not the first attempt. It's the hardest revision. Spend the mental energy upfront — an hour of design is worth weeks in production.