# 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.