From Beginner to Advanced Issues

This roadmap is a deliberately ordered ladder of Firecracker contributions. Each rung trains one skill, depends on the rung below it, and ends at a concrete, review-ready Pull Request on github.com/firecracker-microvm/firecracker. Skipping rungs is the most common reason strong engineers stall here: a virtqueue fix without the virtio transport in your head turns into a months-long PR thread, and a snapshot-compat change without the Persist/versioning reflexes turns into a restore that silently corrupts a customer's microVM state. The stages exist so you climb in the order the codebase rewards.

Firecracker is single-vendor governed: a dedicated AWS team owns it, there is no separate foundation, no JIRA, no CLA. The source of truth is GitHub — issues and Pull Requests. Every commit carries a DCO sign-off (git commit -s, the Signed-off-by: line), new functionality needs an integration test, and merging needs two maintainer approvals. CI is GitHub Actions plus Buildkite; the local pre-flight is tools/devtool checkstyle and tools/devtool checkbuild --all. If you are arriving from a JIRA project, drop the patch-file muscle memory: the unit of work is a branch on your fork and a PR against main.

The stages are calibrated to the Firecracker main branch (v1.16 era; swagger 1.17.0-dev — verify on your branch). The codebase recently went through a large refactor that merged most crates into a single vmm crate, so almost everything you read lives under src/vmm/src/. Where a stage names a module it uses the current top-level shape you will see in a checkout:

src/vmm/          the core VMM library — machine model, vCPU/KVM state, ALL device emulation,
                  snapshots, mmds, rate limiting, seccomp install, logging. The big crate.
src/firecracker/  the firecracker binary + the HTTP API server (src/firecracker/src/api_server/)
src/jailer/       the jailer binary (chroot/cgroups/namespaces/priv-drop, then exec firecracker)
src/seccompiler/  JSON seccomp filter -> BPF compiler (baked into the binary at build time)
src/cpu-template-helper/, src/snapshot-editor/, src/rebase-snap/, src/acpi-tables/, src/utils/
tests/            the pytest integration harness (the primary suite; NOT raw cargo test)
resources/        seccomp JSON (resources/seccomp/), guest kernel configs (resources/guest_configs/)
tools/            devtool — the Docker-based build/test/style driver
docs/             getting-started, jailer, seccomp, snapshotting/, prod-host-setup, ...

Note: Code moves between branches and the refactor is recent. This roadmap never cites line numbers and rarely cites exact paths without an rg/find to locate the thing on your checkout. When you see a struct or function named, run the command next to it. A contributor who trusts a memorized line number is already wrong.


The Twelve Stages

The ladder runs from changes a reviewer will barely have to think about (docs, a missing test) to changes that can hold a release (regressions, CVE-class fixes). The left half is about the contribution mechanics and the request/config path; the right half is about the correctness-critical core — the vCPU, the devices, snapshots, security — where a bug can crash a guest, leak across a tenant boundary, or corrupt restored state.

#StageTarget skillPrereq levelPrimary subsystemTypical PR size
1Docs & testsGitHub flow, DCO, CHANGELOG, devtoolnonedocs/, comments, unit tests1–40 lines
2Build, tooling & loggingdevtool, clippy/fmt, log messages, CI1–2tools/, logger/, build scripts5–80 lines
3Error messages & diagnosticsRust error enums, thiserror, context2–3*Error enums across vmm20–150 lines + test
4API & config validationrequest parsing, vmm_config bounds checks3vmm_config/, rpc_interface.rs30–250 lines + test
5Device configurationblock/net/vsock/balloon config, rate limiter, MMDS3, 7vmm_config/, rate_limiter/, mmds/40–300 lines + test
6vCPU & KVMrun loop, VcpuExit, ioctls, CPUID/MSR4vstate/vcpu/, cpu_config/, arch/40–400 lines + test
7Virtio devicesvirtqueues, feature negotiation, I/O correctness7devices/virtio/50–500 lines + test
8Snapshot compatibilityPersist, MicrovmState versioning, restore9persist.rs, snapshot/, device Persist implssmall code, long thread
9Flaky testspytest harness, races, timing, tests.seed5tests/, *_test.rs20–150 lines
10Performanceboot time, mem overhead, io_engine, perf CI9hot paths in vmm, tests/integration_tests/performance/30–300 lines + numbers
11Security & seccompseccomp filters, jailer, attack surface9resources/seccomp/, seccomp.rs, jailer/small code, security review
12Release-blockingregression triage, release policy, CVE handlingmaintainerwhole-projectvaries

Stages 6–8, 10, and 11 share a prerequisite band rather than a strict order: once you have the vCPU run loop and the virtio transport in your head (Levels 4 and 7), you can branch into KVM edge cases, virtqueue bugs, snapshot versioning, performance, or seccomp depending on the issue in front of you. Stage 9 (flaky tests) sits off to the side — it needs the pytest harness fluency of Level 5 but not the deep subsystem knowledge, so many contributors interleave de-flaking work with everything else.


How Firecracker labels map to stages

Firecracker issues are labelled on GitHub. There is no component tree; a combination of type, status, priority, and a few special labels does the same job. Every stage's issue search is built from these. The exact strings drift across releases — verify the current set on the tracker rather than memorizing them:

# List the live labels (names + descriptions). Run this before trusting any label string below.
gh label list --repo firecracker-microvm/firecracker --limit 100
Label (verify on the tracker)MeaningWhich stages use it
good first issuecurated, small, mentor-friendly1, 2
Type: Bugincorrect behaviour3–12
Type: Enhancementnew behaviour / improvement2, 4, 5, 10
Type: Documentationdocs / comments / help text1
Type: Performancelatency, throughput, memory overhead10
Status: ... (e.g. Awaiting review, Parked)lifecycle statescope by these
Priority: ... (High/Medium/Low)maintainer-assigned urgency12 weighs these
Kaniformal-verification (model-checking) workadvanced; vstate/virtio proofs
Roadmap: ...tracked larger initiativesread, don't blindly patch

The canonical search, reused (with different labels) in every stage:

# Open, unassigned, recently touched — paste the equivalent into the GitHub search box too.
gh issue list --repo firecracker-microvm/firecracker \
  --state open --label "good first issue" --search "no:assignee sort:updated-desc" --limit 30

no:assignee is the single most useful filter: it skips issues someone is already working. Each stage also gives at least one fallback rg to find a candidate in the source when labels return nothing — because in a single-vendor project, many real bugs are filed by the team without a tidy good first issue tag.


How to use this roadmap

Pick a stage honestly

Find your rung by asking what is the largest change you have shipped to Firecracker:

  • Never landed a Firecracker PR → start at Stage 1.
  • Landed a docs PR but never touched Rust in src/vmm/ → Stage 2.
  • Comfortable reading vmm but never traced an API request to a VmmAction → Stage 3–4.
  • Read the vCPU run loop once and were confused → Stage 6 after redoing Level 4.
  • Could draw the virtio split-virtqueue from memory → Stage 7+.
  • Already a maintainer-track contributor → Stages 10–12 for sharpening.

Do not jump rungs to chase a "cool" bug. An unhandled VcpuExit looks self-contained and isn't — the fix lands on the run-loop dispatch you have never instrumented and a KVM contract you have never read (Stage 6 prerequisite work). The roadmap rewards small surface area arrived at honestly.

One concern per PR, one CHANGELOG line per release

Firecracker reviewers reject mixed-concern PRs reflexively. One logical change per commit, each commit passing tests on its own. User-visible changes add a one-line entry to CHANGELOG.md under the unreleased heading. If you cannot name your change in one line, it is doing too much — split it and file a follow-up issue.

Always start with git log and git blame

Before touching a file, find who cares about it and how it last changed:

git log --oneline -n 8 -- src/vmm/src/devices/virtio/block/
git blame -L 1,60 src/vmm/src/devices/virtio/block/device.rs   # who last touched this region

The blame output tells you which maintainer owns the area — useful context when you write the PR description, and a fast way to find the test that guards the code (the same commit usually added it).

Read the workflow once, then never re-explain it

Every stage from 2 onward assumes the Stage 1 mechanics: fork → branch → DCO sign-off → CHANGELOG entry (if user-visible) → tools/devtool fmt → tools/devtool checkstyle → tools/devtool checkbuild --all → PR → read CI → respond to review. Stage 1 drills all of it. Later stages spend their words on code.

Open a discussion before you write code (Stage 4 and up)

For anything touching the device model, the vCPU, snapshots, or security, comment on the issue with a three-sentence plan before the diff:

I see <symptom> at <module> (rg below). My read is <cause>. I plan to <fix>, with an
integration/unit test in <test file>. Anything I'm missing before I open a PR?

In a single-vendor project the maintainers know the unstated invariants — the minimal-device-model philosophy, the snapshot wire format, the seccomp allow-list rationale. Three sentences first saves weeks. This matters more here than in most projects because "QEMU has it" is explicitly not an argument: added surface area faces a high bar.

Time investment per stage

Calibrated against a contributor who has the repo checked out, can run tools/devtool build and tools/devtool test, and has opened at least one PR:

StageFirst PRBecoming fluent (≈5 PRs merged)
1half a day1 week
21 day2 weeks
31–2 days3–4 weeks
42–4 days1–2 months
53–6 days2–3 months
61–2 weeks3–6 months
72–4 weeks6 months
82–4 weeks (compat review)6+ months
91–3 days per flakeongoing
10weeks (bench-bound)maintainer-level skill
11weeks (security review)maintainer-level skill
12maintainer responsibilityn/a

What to read alongside this roadmap


What this roadmap is not

It is not a tutorial on Firecracker itself. The deep dives cover the architecture; the labs from Level 1 onward cover hands-on code reading. The roadmap assumes you can already build from source, run tools/devtool test, and boot a microVM by hand from your own build. If you cannot, the prerequisite is Level 1.

It is not a generic open-source guide either. CONTRIBUTING.md, docs/, and the PR template in the repo cover account setup, the DCO mechanics, and the test commands; the roadmap assumes you read them once. And it is not a roadmap to maintainership — that path the AWS team manages (see the maintainer mindset). The roadmap teaches the skills that, applied consistently, make maintainership a realistic outcome. Landing PRs is necessary, not sufficient.


How the stages interlock

Each stage builds vocabulary the next stage uses without re-explaining:

  • Stage 1 teaches the PR artifact: fork, DCO, CHANGELOG, devtool. Every later stage assumes it.
  • Stage 2 teaches the build/style gates and Firecracker's logging idioms. Stage 3 builds on the logging discipline with the rule that every error carries actionable context.
  • Stage 3 teaches the *Error enums and how a failure surfaces to the API caller. Stage 4 follows the request earlier — into request parsing and vmm_config validation, before a bad value ever reaches a device.
  • Stage 4 teaches config validation in the abstract. Stage 5 applies it to the real devices: block, net, vsock, balloon, the rate limiter, MMDS — and starts touching device internals.
  • Stage 6 teaches the vCPU/KVM layer beneath every device. Stage 7 teaches the virtio device model that rides on top of it. These two are the correctness-critical heart of the VMM.
  • Stage 8 teaches snapshot/restore and the Persist trait — which requires understanding the device state from Stages 5–7 and the versioning discipline that makes a saved microVM restorable on a different binary.
  • Stage 9 teaches deterministic testing. Stage 10 uses that determinism as the baseline for stable benchmarks. Stage 11 treats every change as an attack-surface change. Stage 12 weighs all of it when deciding whether an issue blocks a release or merely waits for the next one.

Skipping a stage means skipping a vocabulary. Reviewers will notice.

Now turn to Stage 1.