NOTICE: I've summarized the perspectives of Octane's and Solid's creators here, for anyone short on time: https://gist.github.com/aleclarson/829c10aa7d287944ef75e1c2a90bef06
I'm a React/Preact/Astro developer with an interest in other renderers. The two that have most caught my eye recently are Octane (from Dominic Gannaway of React Hooks / Svelte / Inferno fame) and Solid 2.
I asked ChatGPT to compare them with its own "Renderer DX Pillars", which I've shared below. This is its gut instinct, with very little hedging:
| Pillar | Winner | Why |
|---|---|---|
| State architecture freedom | Solid 2 | Reactivity is independent of components. Much less component gravity. |
| Reactive reasoning | Solid 2 | The dependency graph is explicit and causal. Easier to answer “why did this update?” |
| Derived state & synchronization | Solid 2 | Fine-grained derivation is the native model; less need to coordinate state manually. |
| Async/data flow | Solid 2 | This is basically Solid 2's flagship idea. Async being part of reactivity feels deeper than improving Suspense/hooks ergonomics. |
| Component authoring | Octane | Normal values, normal functions, familiar TSX, fewer Solid-specific semantic gotchas. |
| Escape hatches | Solid 2, narrowly | Solid's primitives compose very directly with imperative JS without pretending everything is a component concern. |
| Ecosystem interoperability | Octane | If its React-ecosystem compatibility ambitions work, this could be a huge advantage. |
| Tooling & debuggability | Solid 2 today | More mature and battle-tested. Octane's compiler creates more invisible machinery that tooling has to explain well. |
| Architectural scaling | Solid 2 | Its reactive model naturally lets domain/application architecture exist independently of rendering. |
So my gut scoreboard is:
Solid 2: 7 Octane: 2
But the two Octane wins are meaningful ones.
Its pitch seems particularly strong around:
“I want React's authoring experience without React's runtime/design baggage.”
You get something like:
function Counter() {
const [count, setCount] = useState(0);
const doubled = count * 2;
return <button onClick={() => setCount(count + 1)}>
{doubled}
</button>;
}That's extremely approachable.
Solid asks you to internalize:
const [count, setCount] = createSignal(0);
const doubled = () => count() * 2;which isn't hard, but it is a different programming model.
So for day-one DX, I wouldn't be surprised if Octane feels better.
Solid's advantages seem to accumulate as the application becomes less like:
some components with state
and more like:
a complex reactive application that happens to have a UI.
That's where signals outside components, ownership, fine-grained derivation, async graph semantics, stores, and independent domain state all start reinforcing each other.
My gut says the trajectory looks something like:
small app
Octane ██████████
Solid █████████
↓ complexity
large/stateful app
Octane ████████
Solid ████████████
Not because Octane necessarily scales poorly, but because Solid's abstraction seems closer to the actual problem being modeled once state relationships get complicated.
Escape hatches.
Octane could easily end up winning there if its compiler makes effects, refs, subscriptions and integration code extraordinarily pleasant.
And ecosystem interoperability could become an overwhelming Octane win if their compatibility layer is genuinely broad and reliable rather than “we have adapters for the popular demos.”
If I had to assign confidence rather than points:
- Solid strongly wins: state architecture, derived state, async, architectural scaling.
- Solid probably wins: reactive reasoning, escape hatches.
- Octane strongly wins: initial component authoring.
- Octane probably wins: ecosystem interoperability.
- Solid wins for now: tooling/maturity.
The biggest question I'd personally want answered before choosing between them is therefore not performance.
It's:
Does Octane's compiler actually eliminate the architectural drawbacks of component-centric reactivity, or does it mostly make that model much nicer to write?
If it's the latter, I'd expect Solid 2 to remain the stronger foundation for complex applications.
It's a good thread. Let me respond to that feedback though:
Octane is alpha, and this is exactly the kind of criticism that should help shape it.
Solid has a real advantage in making reactive relationships and async state part of one runtime model. I don’t think Octane should pretend that inferred dependency arrays or better-scheduled Suspense are the same thing.
My longterm bet, and this one I've had for a while from Ripple, is that a compiler-owned language can take substantially more responsibility for correctness, caching, scheduling, and state coordination than today’s React-shaped APIs suggest. We already use that approach for hook identity, dependency inference, derived-value caching, and independent async work. There is considerably more room to explore. However it's not always easy to convey this to the general audience too. There's been a lot of push back over compiler driven logic because it's still very new.
That does not mean the compiler gets to guess silently. Explicit dependency arrays remain authoritative today (you can opt into them when you think you need, them or LLM does) but generally they aren't needed for most cases. When the compiler analysis cannot establish something safely inferred, we need a clear contract, a conservative result, or an actionable error. We also need to explain what the compiler decided and connect that explanation to what happened at runtime (more work to do here though).
Increasingly agent-authored software changes which constraints are practical. An agent can handle a substantial refactor in response to a precise compiler diagnostic. That makes it more practical to reject patterns that are convenient locally but difficult to reason about globally. Humans still decide what the application should do; the compiler should make more of that intent enforceable.
"use strong"is an early step – it's a compiler feature for Octane that literally blocks things at compile time with no override (so not a linter where you can just ignore it). I wanted to explore a stronger world where manualuseMemoanduseCallback, etc are unnecessary, anduseEffectis no longer the general-purpose mechanism for co-ordinating application state. Eventually, I would like strong application code to be able to prohibit all three. But that only works if we provide better primitives for derivation, actions, resources, subscriptions, and genuine external synchronisation. That's why we broughtuseLinkedState, added a third param touseStateand have plans onuseAsyncExternalStoreto fix a whole category of issues there. Not only that, but we're deep in the cross-module compilation where we use TS native to determine props and types between components and modules, many levels deep, to avoid needing a dependency because we know it doesn't change. Literally, the work we're doing in compilation is beyond anything else that has happened since Prepack (I miss Prepack a lot).Every restriction needs to buy a useful guarantee. Every removed API needs a better way to express its legitimate uses. And the resulting system needs to be understandable by people and agents when something goes wrong.
That experience is part of why I find this comparison interesting. Solid’s runtime graph offers real benefits, particularly around causality, shared derivation, and async state. I’ve worked on those ideas myself. Octane is a deliberate exploration of another part of the design space: how much responsibility can a compiler take while preserving ordinary values, familiar component authoring, and understandable runtime behaviour? I mean, I was the person that first invented the async idea for Svelte 5, and I'm glad it's made its way into Rich Harris's hands to implement and further improvised on and tuned by Ryan – that's why we do OSS.
I just find it kind of a weak one. It kind of feels like who can make a better garbage collector problem. I've had the experience of building a garbage collector in my engineering history and it's fascinating as, still today, no one has built the perfect one. That's because there isn't a perfect one. There also doesn't need to be a perfect one. There doesn't need to be a perfect async model either, the architecture and design of one doesn't mean we need one, having one is exciting, but then you'll also likely miss something later down the line and have even more frustration. I still have this with both Solid and Svelte 5's async design – you have a colouring problem when you don't know what signal is sync and what is async. The type-system doesn't tell you. The naming of the variable, property or method doesn't tell you – do you invent a $ suffix? Do you craft some internal logic that says "this might be an async signal", you just don't know. No one really knows – but a compiler, well that crafty thing is deterministic and it can know.
Anyway, like I said, Octane is still alpha. It's current React-shaped API is a useful starting point, but I don’t see it as the ceiling. As more software is written with agents, stronger language constraints become practical: the compiler can reject ambiguous patterns, explain what guarantee was violated, and give an agent a clear path to repair the code.
My experience gives me reasons to pursue this direction. It doesn’t exempt Octane from proving that it works.
I’m not claiming Octane has already solved all of that. I am saying its current React-shaped surface should not be mistaken for the limit of its ambition.