java-prod-skill
Skill1 starsChanged 3 months agoMITView on GitHub
Java production readiness patterns. Load for "prod review", "production review", "review for production", "make production ready", or "productionize" on Java code.
In this repository18 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- clickhouseSkill
- distributed-systemsSkill
- flink-javaSkill
- flink-pythonSkill
- flink-sqlSkill
- gitSkill
- grokSkill
- javaSkill
- mermaid-skillSkill
- openapi_docSkill
- postgresSkill
- python-numericsSkill
- pythonSkill
- pytorchSkill
- reactSkill
- rustSkill
- sqlSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 3 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 84
Flags: No correlation ID, logging PII/secrets, empty error logs, wrong log levels, missing box() on primitives, string concat in log calls
- Distinctive: line 99
Prefer immutability and thread confinement over synchronization.
- Distinctive: line 122
Flags: No size limits on input, SQL concatenation, unsanitized paths, no rate limiting
- Very specific: line 142
Use framework health endpoints (SmallRye @Liveness/@Readiness, Spring Actuator - see java-skill references), never hand-rolled /health.
- Distinctive: line 144
Flags: No health endpoint, dependency checks wired into liveness, no latency/error metrics, no alerting
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Production Readiness
Patterns for reviewing production-grade Java code. Complements java-skill.
Resource Management
Set timeouts on ALL external calls. Use try-with-resources. Implement graceful shutdown.
var client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();
var request = HttpRequest.newBuilder(uri).timeout(Duration.ofSeconds(30)).build();
// Graceful shutdown pattern
@Override public void close() {
executor.shutdown();
if (!executor.awaitTermination(30, TimeUnit.SECONDS)) { executor.shutdownNow(); }
}Flags: Missing timeouts, resources not in try-with-resources, no shutdown hook
Retry & Resilience
Retries need exponential backoff and max attempts. Circuit breakers prevent cascade failures.
Failsafe (dev.failsafe:failsafe) is the house library: RetryPolicy + CircuitBreaker + Timeout composed via Failsafe.with(...). The loop below is the zero-dependency shape to recognize in review.
Result<Response> callWithRetry(Request req) {
for (int attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
switch (call(req)) {
case Ok(var r) -> { return Result.ok(r); }
case Err(var f) -> {
if (attempt == MAX_ATTEMPTS || !isRetryable(f)) { return new Err<>(f); }
}
}
sleep(BASE_DELAY.multipliedBy(1L << (attempt - 1))); // exponential backoff
}
return Result.err("EXHAUSTED", "max retries exceeded");
}Circuit breaker: track failures, open circuit after threshold, allow probe after timeout.
Flags: Retry without backoff (thundering herd), backoff without jitter (still synchronizes retry waves), hand-rolled retry where Failsafe is available, no max attempts, no circuit breaker on external deps
Logging & Observability
Log4j2 garbage-free mode with correlation IDs. Propagate ThreadContext across virtual threads. Garbage-free MDC is off by default: it requires log4j2.garbagefreeThreadContextMap=true (full prod config: java-skill references/log4j2.md).
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
import static org.apache.logging.log4j.util.Unbox.box;
private static final Logger log = LogManager.getLogger();
ThreadContext.put("correlationId", correlationId);
try {
log.info("order started: orderId={}, items={}", orderId, box(items.size()));
// ...
log.info("order complete: orderId={}, status={}, durationMs={}", orderId, status, box(elapsed));
} finally {
ThreadContext.clearAll();
}
// Virtual thread ThreadContext propagation
var contextMap = ThreadContext.getImmutableContext();
executor.submit(() -> {
ThreadContext.putAll(contextMap);
try { process(); }
finally { ThreadContext.clearAll(); }
});Logging rules: box() all primitives, () -> supplier for expensive args, {} placeholders only (never string concat).
Flags: No correlation ID, logging PII/secrets, empty error logs, wrong log levels, missing box() on primitives, string concat in log calls
Configuration
Externalize environment-specific values. Never hardcode secrets. Use feature flags for risky changes.
@ConfigProperty(name = "service.timeout.seconds", defaultValue = "30") int timeoutSeconds;
@ConfigProperty(name = "feature.new-flow.enabled", defaultValue = "false") boolean newFlowEnabled;Flags: Hardcoded secrets/API keys, magic numbers, no feature flags for risky changes
Concurrency Safety
Prefer immutability and thread confinement over synchronization.
- Thread-confined: each virtual thread gets own instance
- Shared state: use
ConcurrentHashMap, atomic types - Bounded executors:
LinkedBlockingQueue(capacity)+CallerRunsPolicyfor backpressure
Flags: Shared mutable state without sync, unbounded queues/pools, busy-wait, blocking on platform threads
Input Validation & Security
Validate at boundaries. Size limits prevent DoS.
Result<Order> createOrder(OrderRequest req) {
if (req.items() == null || req.items().isEmpty()) { return Result.err("VALIDATION", "items required"); }
if (req.items().size() > MAX_ORDER_ITEMS) { return Result.err("VALIDATION", "max items exceeded"); }
// ...
}- Parameterized queries only - NEVER concatenate SQL
- Sanitize file paths:
Path.of(filename).getFileName()+ verify within base dir
Flags: No size limits on input, SQL concatenation, unsanitized paths, no rate limiting
Database
Scope transactions tightly. Prevent N+1 queries.
// BAD: N+1 queries
for (var order : orders) { var items = itemRepo.findByOrderId(order.id()); }
// GOOD: batch fetch
var itemsByOrder = itemRepo.findByOrderIds(orderIds).stream().collect(groupingBy(Item::orderId));Flags: Long transactions, N+1 patterns, missing indexes, per-request connections
Health & Metrics
Expose health checks. Track: latency (p50/p95/p99), error rate, throughput, queue depth, pool utilization.
Use framework health endpoints (SmallRye @Liveness/@Readiness, Spring Actuator - see java-skill references), never hand-rolled /health. Dependency checks belong in readiness, never liveness: DB-down should shed traffic, not trigger restarts.
Flags: No health endpoint, dependency checks wired into liveness, no latency/error metrics, no alerting
Review Output Format
## Production Readiness: [READY | NEEDS WORK | BLOCKED]
### Blockers
- [item]: reason
### Warnings
- [item]: reason
### Verified
- Resource management (incl. timeouts): OK
- Retry & resilience: OK
- Logging & observability: OK
- Configuration: OK
- Concurrency safety: OK
- Input validation & security: OK
- Database: OK
- Health & metrics: OKDoes it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

