# Engineering Guide ## 1. Key Principles > These are the non-negotiable core ideas we bring into everything we build. Builder, orderflow integrations, telemetry etc. > We move fast, and keep systems simple and clean so we can keep shipping. - **You own what you ship** The engineer writing the code is responsible for correctness, clarity, impact and delivery. If it breaks, you fix it. If it’s unclear, you clarify it. - **We own the system together** An important follow-up to the above point. There’s no “not my code”. If you see something broken, unclear, or slow - fix it or flag it. Everyone is responsible for the state of the codebase, not just the original author. - **Code is a liability** Fewer lines = less to reason about, less to break, less to maintain. Delete aggressively. If something isn’t essential, remove it. - **Tight local feedback loops** Every part of the system must run locally and mimic production closely. Fast iteration is an exponential leverage. If something can’t run locally, fix that first. - **Simplicity over complexity** Simple, predictable designs are easier to optimise, debug, and scale. Be concise. Complexity spreads fast and kills performance. - **Contain complexity** Keep modules tight. Keep scope narrow. Keep interfaces explicit (do not pub use ::* everything...). Complexity that leaks across boundaries causes spaghetti. > Our priorities for code match our principles: > 1. **Correctness** – the system must behave deterministically. If it’s wrong, nothing else matters. > Correctness comes from clear, contained systems without unnecessary complexity. > 2. **Performance** – speed is a large part of our edge and pnl. > 3. **Maintainability** – simple code is faster to iterate on and easier to reason about. > > Everything else follows from these. Keep these in mind when designing, reviewing, or rewriting. --- ## 2. Reviews > Reviews are one of the most important, and most overlooked, parts of being an engineer. High standards in reviews = high standards in the system. Treat them as first-class. ### Pull Requests - Keep PRs scoped and clear. - Never mix large refactors with business logic changes. - Cosmetic refactor → separate PR (skim quickly). - Logic change → separate PR (deep review). - If there are business logic changes include a short rationale: what changed, why it matters, how to review (e.g., key files changed). ### Reviews - Reviewing is *not optional*. It’s part of being an engineer. - No one works alone. No big code changes go to production without review. - Do not skim changes. If you don’t understand the change, ask questions or get the right reviewer involved. Don’t let unclear code merge. - If you see something sloppy, call it out. Everyone owns quality. - There's more than one good way to implement something. Don't bikeshed. Review comments should be substantive and backed by reason. > Strong review culture requires work from both sides. PRs must be scoped and reasonable. Reviews must be done thoroughly and promptly (should be ≤1 day). --- ## 3. Framework for our High-Performance Systems > This is the core of our infra. Everything else sits around it. Even when building systems that aren't on the hot-path it's still important to understand these principles. ### Core Ideas - One stage = one responsibility. - Message passing, not shared locks. - Timing for every stage, for every message. ### How It Looks - **Pipeline** The system is built from well-defined stages (tiles). Each tile has a single responsibility, runs pinned on a core, and spins in a tight loop. - **Tile Trait** - Each tile implements a Tile trait with setup, pinned loop, and teardown. - Each tile owns its core. - Tiles are isolated - no shared mutable state between them. - **Communication** - Lightweight, copy messages are sent through broadcast queues. - Any dynamic allocations are stored in pre-allocated shared memory. Messages only carry offsets. - **Telemetry / Tracking** - All messages are tracked as `InternalMessage`. - Because queues are broadcast, a separate process can pick up and read everything to display locally (e.g., overseer) or write to DBs. > Core datastructures and types can be found in `gattaca-com/flux` > https://github.com/firedancer-io/firedancer is a great reference and the inspiration for the name "Tile". --- ## 4. More General Code Guidelines - **AI** AI can help, but it’s easy to abuse. Unsupervised changes are messy, overcomplicated, and usually wrong. Don’t ship code you don’t understand. - **Crates** Crates are often overused in the wrong place and underused in the right place. Make a new crate only if it’s actually reused. - Don’t split code into multiple crates for the sake of it. If a component (e.g. bid-submitter) is only ever read by one crate, keep it together. - Do split code into crates if they’re genuinely shared. - Avoid dumping everything into a single “shared” or “common” crate. Keep shared crates focused and minimal so importing one doesn’t drag in everything else. - **Config for the sake of config is a mistake** Are these conditions going to be used. Do they provide a use. If not, do not add. - **Dumping Grounds** Avoid catch-all files like `types.rs`, `utils.rs`, or `mod.rs`. This doesn’t mean one file per struct — that’s also wrong. Group related things together, separate unrelated ones. - **Comments** - Don’t comment the obvious (`// this variable is a count` above `let mut count = 0;`). - Avoid overly verbose doc comments. - Keep comments concise and pointed. - Comment where logic is non-obvious or business rules aren’t clear from code alone. - **Tests** Test enough to be sure it works. Tests should be clear and fast. Don’t build bloated CI or over-engineered tests. Tight local feedback loops and good monitoring do most of work. - **Lints** Run `just fmt` and `just clippy` before every PR. It’s easy and keeps the style consistent. - **Traits** Traits with a single implementation shouldn’t exist. Same principle as config: don’t add traits for the sake of traits. - **Commit Messages** Commits into develop must be clearly named. The history should tell a clear story of what happened - no “wip” or vague messages. Temporary messages are fine on feature branches since they’ll be squash merged, but make sure the final squash commit is clear and to the point. > This guide is always changing. If you see gaps, propose changes.