Java 17's sealed classes are the language's closest approach to algebraic data types — the closed-world type hierarchies that ML and Haskell programmers have used for decades. You declare a sealed interface, list its permitted subtypes, and the compiler rewards you with exhaustiveness checking on switch expressions. No default clause needed. Forget a case, get a compile error. It's the kind of thing that makes a type-system person's heart rate slow down. The author walks through the mechanism cleanly. A sealed interface SealedType permits TypeA and TypeB as inner records. A switch expression in main pattern-matches against both cases without a default branch, and the compiler is satisfied. This is the pitch: your code is provably complete against the type's shape. If you've written Rust enums or Haskell data declarations, the shape is instantly familiar. But here's where it gets interesting — and where the post earns its keep. Adding a TypeC to the sealed interface is a source-level breaking change. Any consumer that exhaustively matched on two cases now fails to compile. That's expected, and in fact desirable within a single compilation unit. The problem is that Java's compilation model doesn't enforce recompilation across module boundaries. If you recompile the sealed type but not its consumer, the missing case silently becomes a runtime MatchException instead of a compile-time error. This is a genuinely important subtlety. The exhaustiveness guarantee is a compile-time property, not a runtime property. The JVM doesn't enforce it. Separate compilation — the thing that makes Java's ecosystem of JARs and modules practical — is exactly the thing that defeats the safety promise. You get Haskell-grade checking inside your build, and C-grade surprises across builds. The practical conclusion is well-drawn: sealed types are excellent for internal implementation where everything recompiles together, and actively dangerous in public APIs where consumers may not recompile when you ship a new version. Adding a subtype to a public sealed interface is a SemVer major-version bump, and even that only helps if consumers actually rebuild. The author flags a real-world example: Java's preview PEM-encoded cryptographic objects API bakes a sealed interface into its public contract and encourages pattern matching against it — a design that virtually guarantees breakage when new cases arrive. This is a blog post, not a paper, but it functions as a compact technical essay that identifies a design tension most Java developers haven't thought through. The insight isn't that sealed classes exist — that's old news. The insight is that Java's module and compilation model creates a gap between the static guarantee and the runtime reality, and that gap has API-design consequences that the language's own standard library previews are getting wrong. For anyone designing Java APIs or evaluating whether to expose sealed types across module boundaries, this is twenty minutes well spent. It won't change how you think about type theory, but it will change where you deploy sealed types — and that's the more useful intervention.