- Use `native-image` to compile to native executables for fast startup and low memory footprint.
- Declare all reflection usage in `reflect-config.json` — GraalVM's closed-world analysis needs static declarations.
- Avoid dynamic class loading (`Class.forName()`, `ServiceLoader`) — use compile-time alternatives.
- Use `@RegisterForReflection` (Quarkus) or `@TypeHint` (Spring) annotations instead of runtime reflection discovery.
- Avoid `java.lang.reflect.Proxy` — use interfaces and compile-time generated implementations.
- Use `--initialize-at-build-time` for classes safe to initialize during compilation.
- Use GraalVM's polyglot API (`Context`, `Value`) for multi-language interop when needed.
- Prefer Quarkus or Micronaut over Spring Boot for native-image — they're designed for AOT from the ground up.
- Avoid runtime bytecode generation (CGLIB, Javassist) — use compile-time annotation processing instead.