Scarlet Beast Scarlet Beast Hunting Truth in a World of Shadows
Transmissions
NEWStartup Frameworks are for sale — buy a launch-ready business, not a slide deck.Sep 04 NEWTech’s Tinder — a swipe-to-match deal engine for hardware buyers and sellers — joins the framework catalogue.Sep 04 NEWSignal — the creators network for the people who build the machines (formerly networkedin) — joins the framework catalogue.Sep 03 NEWScarlet Beast Poker is packaged for acquisition — platform, native apps, the Hiss AI and the public API.Sep 03 LIVEBusiness Plans — every scope, timeline and price we quote, in one vault.Sep 01 NEWFree technical audit — one call, no pitch, a written findings list you keep either way.Aug 28 LIVEGROWL — the crypto and forex exchange, plus an algorithmic bot marketplace.Aug 26 LIVEHiss — production poker AI: deep reinforcement learning, computer vision, real-time inference.Aug 22 NEWPerformance engineering — measurable TTFB, LCP and CLS gains on enterprise traffic.Aug 18 NEWAdobe Commerce and Shopify Plus modernization — migrations that ship without downtime.Aug 05 NEWThe technology stack is published — what we run, why we chose it, what it costs.Aug 01 NEWStartup Frameworks are for sale — buy a launch-ready business, not a slide deck.Sep 04 NEWTech’s Tinder — a swipe-to-match deal engine for hardware buyers and sellers — joins the framework catalogue.Sep 04 NEWSignal — the creators network for the people who build the machines (formerly networkedin) — joins the framework catalogue.Sep 03 NEWScarlet Beast Poker is packaged for acquisition — platform, native apps, the Hiss AI and the public API.Sep 03 LIVEBusiness Plans — every scope, timeline and price we quote, in one vault.Sep 01 NEWFree technical audit — one call, no pitch, a written findings list you keep either way.Aug 28 LIVEGROWL — the crypto and forex exchange, plus an algorithmic bot marketplace.Aug 26 LIVEHiss — production poker AI: deep reinforcement learning, computer vision, real-time inference.Aug 22 NEWPerformance engineering — measurable TTFB, LCP and CLS gains on enterprise traffic.Aug 18 NEWAdobe Commerce and Shopify Plus modernization — migrations that ship without downtime.Aug 05 NEWThe technology stack is published — what we run, why we chose it, what it costs.Aug 01
Markets
BTC$79,738▲ +0.40%ETH$2,459▲ +0.41%SOL$103.15▲ +1.63%XRP$1.41▲ +0.48%BNB$763.51▲ +6.83%ADA$0.2165▲ +1.01%DOGE$0.0874▲ +2.81%LINK$11.84▲ +1.76%AVAX$7.54▲ +2.51%DOT$0.9176▲ +7.97%LTC$53.59▲ +6.43%TRX$0.3331▲ +1.43%BTC$79,738▲ +0.40%ETH$2,459▲ +0.41%SOL$103.15▲ +1.63%XRP$1.41▲ +0.48%BNB$763.51▲ +6.83%ADA$0.2165▲ +1.01%DOGE$0.0874▲ +2.81%LINK$11.84▲ +1.76%AVAX$7.54▲ +2.51%DOT$0.9176▲ +7.97%LTC$53.59▲ +6.43%TRX$0.3331▲ +1.43%
GROWL feed
Java · Part I

The Machine

You already know how to make a computer do a thing. What you need from Java is the set of ideas that make its programs shaped the way they are — because those ideas, not the syntax, are what your agent cannot supply and what a reviewer will judge you on.

The Frameworks

Containers, proxies, mapping, transactions — the parts every Java framework is made of

The Ten

The ten technologies worth knowing, and what each one is really for

The Practice

How to learn this when an agent writes the syntax for you

1 · The JVM is a platform, not a runtime

PHP and Python each have an interpreter that exists to run one language. The JVM is a general-purpose virtual machine with a published instruction set, and Java is merely its best-known source language — Kotlin, Scala, Clojure and Groovy all compile to the same bytecode and interoperate at the object level. That is why "a Java shop" often means "a JVM shop".

Compilation happens twice. javac turns source into bytecode, which is portable and not especially fast. Then the JIT compiles hot bytecode into machine code while the program runs, using facts it can only know at runtime: which branch actually gets taken, which type actually shows up at a call site, whether a lock is ever contended. A long-running JVM is therefore faster after an hour than after a second.

The mental model

The JVM is a profiling optimiser wearing a runtime as a disguise. It speculates — inlines a method assuming the type it has always seen, elides a lock nobody contends — and holds a deoptimisation escape hatch for when the speculation turns out wrong. Almost everything strange about Java performance follows from that: warmup, why benchmarks lie, why a microservice that restarts every ten minutes never gets fast.

Where this bites

Serverless and aggressive autoscaling are hostile to this design: you pay the warmup and never collect the winnings. That single fact is why GraalVM native images and Quarkus exist — they trade peak throughput for starting fast. Choosing between them is an architecture decision, not a preference.

2 · The process model — the real shift from PHP

This is the idea to internalise first, because everything else inherits from it. PHP is shared-nothing: a request arrives, an interpreter builds a world, the response goes out, the world is destroyed. Global state is a per-request illusion and leaks are bounded by the request.

A Java server is one long-lived process holding many requests at once. Objects outlive requests. Caches are real caches. A static field is genuinely global, shared by every concurrent request, for the life of the process.

ConcernPHP / FPMJava / JVM
LifetimeOne requestDays or months
Shared stateOnly in Redis/DBIn the heap, by default
A leakFreed at request endGrows until OOM
Warm cachesExternal only (opcache aside)Free, in-process
ConcurrencyProcesses, isolatedThreads, sharing memory
Startup costPaid per request, smallPaid once, large

The mental model

Java trades the safety of amnesia for the power of memory. Everything Java gives you — real in-process caches, connection pools, background schedulers, hot JIT code — comes from the process remembering. Everything Java asks of you — thread safety, leak discipline, careful statics — is the bill for that same memory.

3 · Memory: the heap and the collector

You never free anything. The garbage collector traces from a set of roots (stack frames, statics, live threads) and anything unreachable is reclaimed. The consequence is not "memory is free"; it is that memory pressure becomes latency, because collection costs CPU and sometimes pauses.

Modern collectors lean on the generational hypothesis: most objects die young. So the heap is split, new objects land in a small nursery that is collected cheaply and often, and the few survivors are promoted to an old region collected rarely and expensively. Which collector you run is a latency/throughput choice: G1 is the balanced default, ZGC and Shenandoah are built for sub-millisecond pauses on large heaps, Parallel maximises raw throughput and does not care about pauses.

Where this bites

Two failure shapes worth recognising on sight. Allocation churn: code that allocates furiously in a hot loop keeps young collections running constantly — throughput dies without any single slow method. The unintentional cache: a static map that is only ever written to. It is not a leak in the C sense; every entry is reachable, which is exactly why it is never collected. Java's characteristic memory bug is accidental reachability, not forgetting to free.

4 · Types as a design tool

Java's type system is nominal and checked ahead of time. Coming from PHP and Python, the temptation is to treat that as ceremony. It is better understood as machine-checked documentation: a contract the compiler enforces and, more importantly, that tooling and an agent can read. The richer your types, the more of your intent survives contact with other people — and the better your AI's output, because the compiler rejects its wrong guesses.

The mental model

In a dynamic language your types live in your head and in tests. In Java they live in the signature, and the compiler is a reviewer that reads every line, never gets tired, and never approves out of politeness. Design the types first and the code becomes mostly obvious.

5 · Concurrency, and why it is the hard part

PHP gives you no threads; Python has a GIL that mostly saves you from yourself. Java gives you real threads over shared mutable memory, which is genuine power and the source of its nastiest bugs — the ones that pass every test and fail in production under load.

The Java Memory Model is the rulebook. Its core idea is happens-before: without an explicit synchronisation edge, one thread is under no obligation to ever see another thread's writes. Not "sees them late" — never, legally, because the compiler and CPU may reorder and cache freely. Locks, volatile, and the concurrent collections exist to create those edges.

The ladder of tools, roughly in the order you should reach for them:

  1. Don't share. Immutable objects and confinement remove the problem.
  2. Share safely. Concurrent collections and atomics — someone else got the memory fences right.
  3. Coordinate. Executors and thread pools: submit work, get a future, never manage raw threads by hand.
  4. Lock. Last, narrowly, with a documented ordering — because two locks taken in different orders is a deadlock.

Virtual threads (Project Loom) are the biggest change to this in twenty years. Platform threads are OS threads: expensive, so you pool a few hundred, so blocking on I/O is disastrous, so the industry spent a decade writing reactive code to avoid blocking. Virtual threads are cheap enough to have millions, and blocking one costs almost nothing. The architectural consequence is that plain blocking code becomes viable again at scale, and much of the reactive complexity becomes optional.

Where this bites

Concurrency bugs are not reproducible on your laptop, and "it worked in testing" is the normal presentation. Treat any shared mutable field reachable from two requests as a defect until you can name the mechanism making it safe.

6 · Errors as an API decision

Java splits failures in two. Checked exceptions are part of a method's signature and callers must acknowledge them; unchecked ones propagate silently up the stack. The distinction is contested, but the intent is useful: checked means "a caller can plausibly do something about this" (the file is missing, the remote said no), unchecked means "this is a bug or an environment failure" (null where there should not be one, database down).

Where this bites

The most common sin in Java codebases is catching an exception, logging it, and continuing — converting a loud failure into a silent wrong answer. The second is wrapping every exception in a generic one and losing the cause. Both are worth spotting in your agent's output.

7 · Classpath, jars and modules

A jar is a zip of classes. The classpath is an ordered list of them, and classes are loaded lazily, by name, first-match-wins. Two jars containing different versions of the same class is legal, and the winner is whichever the loader reaches first — the classic "it works locally" failure. Dependency tools resolve version conflicts for you; shading rewrites a library's package names so two versions can coexist; the module system (JPMS) lets a jar declare what it exports and what it requires, so the mess is at least declared.

The mental model

Your dependency list is not a list. It is a graph, flattened into one namespace at runtime by rules you did not write. Knowing how to print that graph and read a conflict is a genuine Java skill, and it is the first thing to learn about your build tool.

Part II — what every Java framework is made of →

Written for someone who has an agent for the syntax and needs the ideas instead. Nothing here is a code sample on purpose — if you can name the mechanism, you can ask for the code and judge what comes back.