Skip to content

Reactivity with Runes

A rune is a compiler signal — a function-like keyword prefixed with $ — that tells Svelte “this value is reactive.” Runes are not imported and not called at runtime like normal functions; the compiler recognizes them and generates the reactivity machinery around them.

<script>
let count = $state(0); // reactive state
let double = $derived(count * 2); // recomputed when count changes
$effect(() => console.log(double)); // runs when double changes
</script>

The whole model is: mark reactive values with runes, and the compiler wires up the dependency graph. You never write dependency arrays or subscription code — the compiler sees that double reads count and that the effect reads double, and connects them.

Runes are the headline change in Svelte 5. They replaced three separate Svelte 4 mechanisms with one consistent system:

Svelte 4Svelte 5
let count = 0 (top-level let was implicitly reactive)let count = $state(0)
$: double = count * 2 (reactive statement)let double = $derived(count * 2)
$: { … } (reactive block, side effects)$effect(() => { … })
export let name (props)let { name } = $props()

Why the change? In Svelte 4, reactivity was implicit — a plain let at the top of a component was reactive, but the same code in a .js file was not, and $: had confusing edge cases. Runes make reactivity explicit and portable: $state means the same thing in a component and in a .svelte.js module, and the rules are uniform.

flowchart LR
  state["$state — a reactive source"] --> derived["$derived — recomputes from sources"]
  derived --> effect["$effect — runs when its reads change"]
  props["$props — reactive inputs from parent"] --> derived
Runes mark reactivity; the compiler wires the graph
  • $state — reactive state, deep by default for objects and arrays.
  • $derived — cached values computed from other reactive values.
  • $effect — synchronize with the outside world (and why you usually should not).
  • $props / $bindable — component inputs and two-way binding.
  • Advanced$inspect, untrack, and shared reactive state in .svelte.js modules.
What is a rune?
In Svelte 5, what replaced the Svelte 4 `$: double = count * 2` reactive statement?
Why did Svelte 5 introduce runes?