The Two Hard Gates¶
Which rungs: Rung 5 (Concurrency Playground, end of M8) and Rung 8 (ML Capstone, end of M13) Why this file exists: To make it impossible to lie to yourself in M7 or M12 about whether you’re on track
Why “Hard Gate”¶
A hard gate is a rung whose slippage cascades. Missing a soft rung by a month costs you a rung. Missing a hard gate by a month costs you the plan.
Every rung in the ladder is valuable. Two of them are load-bearing. If you remove them, the ladder collapses. Those two are Rungs 5 and 8. Every other rung is either a prerequisite for these two, or a piece of surrounding evidence.
The rest of this file is one thing: the argument for treating these two as non-negotiable, and the exact triage rules if you find yourself behind.
Hard Gate #1 — Rung 5 (Concurrency Playground) — End of M8¶
Calendar¶
Latest acceptable ship date: February 28, 2027 (end of M8)
You should be halfway done by: January 31, 2027 (end of M7)
You should have picked the algorithms and set up the benchmark harness by: January 15, 2027
Why it’s non-negotiable¶
Every rung downstream of Rung 5 requires it:
Rung 6 (JVM Performance) profiles Rung 5’s code. Without Rung 5 you have nothing meaningful to profile.
Rung 7 (URL Shortener) integrates Rung 5’s rate limiter as a component. Without Rung 5, Rung 7’s integration story is missing.
Rung 8 (ML Capstone) is fundamentally an asynchronous, load-tested service. You cannot ship it without a demonstrated ability to reason about contention and throughput — which is what Rung 5 proves.
More importantly, Rung 5 is the first rung where the difficulty is visible. Anyone can knock out 50 programs (Rung 1) or grind LeetCode (Rung 2). Not everyone can ship a benchmarked, contention-tested rate limiter with a JMH suite. This is the rung where a hiring manager scanning your GitHub starts believing you’re a senior engineer, not a diligent student.
And concurrency skill is an asymmetric skill: study partners actively test for concurrency understanding because they know it’s rare. Getting to study day without concurrency evidence in your portfolio is throwing away the highest-leverage signal you can produce.
If you’re behind at end of M7¶
If January 31, 2027 arrives and you have not started Rung 5, execute this triage in order:
Stop Rung 4 immediately. If the blog post isn’t published, pin the repo as-is and move on. Do not “just polish it for one more week.”
Reduce Rung 5’s scope, but not its shape. Two algorithms instead of three. Skip one of the three access patterns in the benchmark. Do not skip Lincheck / contention testing. Do not skip the blog post.
Extend into early M9. Rung 6 can start on March 15 instead of March 1. Rung 6 is a case-study rung and compresses well; Rung 5 does not compress well.
Do not defer to “I’ll come back to it later.” You will not. This is the last time in the plan Rung 5 has room.
What Rung 5 must minimally contain if you’re triaging¶
The minimum viable Rung 5, if you’re pressed:
One rate limiter (token bucket) with a proper contention test
The virtual-threads benchmark with a chart and 3 concurrency levels (not 5)
The blog post — shorter is fine, but it must ship
The JMH benchmarks — non-negotiable
This minimal version is still stronger than 95% of Java portfolios online. Don’t inflate scope past this if you’re on a tight schedule.
Hard Gate #2 — Rung 8 (ML Capstone) — End of M13¶
Calendar¶
Latest acceptable ship date: July 31, 2027 (end of M13)
You should be halfway done by: June 30, 2027 (end of M12)
You should have picked the model and confirmed local inference by: May 15, 2027 (mid-M11, while Rung 7 wraps)
Why it’s non-negotiable¶
The M13 pitch — “I can debug a 15-year-old Java monolith, refactor it toward modern patterns, and ship new services that survive the next 10 years” — is unsupportable without Rung 8. Rungs 1-7 individually prove you studied Java. Only Rung 8 proves you can ship an integrated service.
More concretely:
Rung 8 is the artifact that turns “applied ML engineer refreshing Java” into “applied ML engineer who ships Java-native ML services.” That is the differentiator. Without Rung 8, you are competing with every fresh Java student in the market on identical evidence.
Rung 8 is the only rung that combines ML and Java. That combination is the entire premise of the roadmap. Skip it and the roadmap has failed on its own terms.
The 13-month narrative dies without a capstone. Recruiters don’t read your files — they read the shape of your GitHub. A ladder with a top rung that shows real synthesis is massively stronger than seven parallel rungs of similar signal.
If you’re behind at end of M12¶
If June 30, 2027 arrives and Rung 8 hasn’t shipped a working local prototype, execute this triage in order:
Freeze all polish work on earlier rungs. No more retroactive tests on Rung 2. No more “just one more benchmark” on Rung 6. Every remaining hour goes to Rung 8.
Cut the three-part blog series to a single post. Ship one “how I built it” post in the last week of M13. The series is a stretch; the post is required.
Cut real-cluster deployment. Fall back to Minikube. Losing the paid-cluster “live URL” is a real loss, but not as bad as missing the deadline. Document that Minikube is the demo target and provide a clean startup script.
Simplify the model. If the current model choice is fighting you, pivot to a smaller, simpler one you already understand cold. A shipped simple model beats an unshipped ambitious one.
Do not cut virtual threads. Do not cut hot-reload. Do not cut Kubernetes primitives. These are the load-bearing pieces of the signal. The model can be simpler; the engineering cannot be simpler.
What Rung 8 must minimally contain if you’re triaging¶
The minimum viable Rung 8:
A working
POST /predictendpoint serving a real ML model in-process (not shelled out)Virtual threads for request handling, configured explicitly
Kubernetes manifests that deploy cleanly to minikube in under 5 commands
HPA, probes, resource limits — all present, even if minimal
README with the M13 pitch as the first sentence and an architecture diagram
At least one blog post (of the intended three) shipped
MODEL_CARD.md and ARCHITECTURE.md — short is fine, present is required
Without these, Rung 8 has not shipped. With them, Rung 8 has shipped even if imperfect.
The Meta-Rule: If Both Gates Are At Risk¶
If at any point in the plan you realize both gates are threatened (typically due to a personal emergency around M6-M9), execute this override:
Save Rung 5. Cut Rung 3 or Rung 4 if necessary. Rung 5 is the more valuable of the two because it makes Rungs 6, 7, and 8 all possible.
Compress Rung 6 aggressively. Rung 6 is a case study; a 3-iteration case study is still valuable. A 0-iteration case study is a lie.
Cut Rung 7’s scope, not its shape. Ship a URL shortener without Redis. Without analytics. Without a real deploy — use Fly’s free tier only. But ship something that runs on the public internet.
Never sacrifice Rung 8. If a choice is between shipping Rung 8 and shipping Rungs 3+4+7 all polished, ship Rung 8. The other rungs are stepping stones. Rung 8 is the destination.
The Uncomfortable Question To Ask Yourself Monthly¶
At the end of every month, look at the calendar and ask:
“If today is my last day of study — emergency, job change, family need — do I have a version of Rung 5 and Rung 8 that a stranger could open and understand?”
If the answer is no, and you’re past M7 or past M12, you’re behind. Rearrange next month accordingly.
The plan does not care about your feelings. The plan cares about what ships. Ship the gates.
Return to README.md · Next: 10_publishing_and_visibility.md