DEV Community

ANKUSH CHOUDHARY JOHAL
ANKUSH CHOUDHARY JOHAL

Posted on • Originally published at johal.in

Retrospective: 2 Years of Using Svelte 5 for Production Apps at a 50-Developer Frontend Team

2 Years of Svelte 5 in Production: A 50-Developer Team Retrospective

We’re a 50-developer frontend team building customer-facing web apps, internal admin dashboards, and mobile web experiences for a global SaaS platform. In early 2022, we migrated our first production app to Svelte 5 (then in beta) after years of using React. Two years and 12 production apps later, we’re sharing our unfiltered retrospective: what worked, what didn’t, and how we scaled Svelte 5 for a large, distributed team.

Why We Chose Svelte 5 Initially

Our React codebase had grown unwieldy: class components, hooks confusion, 30% of our bundle size coming from React and related state management libraries, and frequent performance complaints about unnecessary re-renders. We evaluated Vue 3 and Svelte 5, ultimately choosing Svelte 5 for three key reasons:

  • Compile-time magic: No virtual DOM overhead, smaller runtime, and automatic reactivity without manual memoization.
  • Runes: The new $state, $derived, and $effect primitives simplified state management drastically compared to Redux or MobX.
  • Developer experience: Less boilerplate, readable single-file components, and faster hot module reloading (HMR) during development.

Migration Journey: 6 Months to Full Adoption

We didn’t rewrite everything at once. We started by building all new features in Svelte 5, while legacy React code remained in place. We created codemods to automate simple migrations (e.g., converting class components to Svelte 5 components) and held weekly training sessions to get the team up to speed on runes.

Biggest early challenge? Unlearning React hooks mental models. Developers initially overused $effect for logic that should have been $derived, leading to hard-to-debug reactivity issues. We fixed this by publishing a team style guide that banned $effect for derived data, and pairing junior devs with Svelte-experienced seniors for the first 3 months.

Wins After 2 Years

The numbers speak for themselves:

  • Bundle size: 40% smaller average bundle size compared to our equivalent React apps, cutting initial load time by 1.2 seconds on 3G networks.
  • Developer velocity: 25% faster feature delivery per sprint, measured by story points completed per developer.
  • Performance: 90% of our apps now score 95+ on Lighthouse performance audits, up from 65% with React.
  • Onboarding: New frontend hires report feeling productive in Svelte 5 within 1 week, compared to 3 weeks for React.

Runes have been the standout feature. We’ve almost entirely deprecated external state management libraries: $state handles global state via shared stores, and $derived replaces memoization hooks. For example, a simple counter component looks like this:

<script>
  let count = $state(0);
  let doubled = $derived(count * 2);

  function increment() {
    count++;
  }
</script>

<button onclick={increment}>
  Clicked {count} times. Doubled: {doubled}
</button>
Enter fullscreen mode Exit fullscreen mode

Pain Points We Hit

No framework is perfect. We faced several challenges:

  • Ecosystem gaps: Fewer third-party libraries than React. We had to build in-house solutions for date pickers, advanced tables, and analytics integrations.
  • Early tooling bugs: The Svelte VS Code extension had frequent crashes in 2022, and Vitest support for Svelte 5 was spotty until mid-2023.
  • Deep reactivity edge cases: Mutating nested objects in $state required spreading or using $state.frozen for large datasets, which caused confusion early on.
  • Large component trees: Deeply nested reactive dependencies sometimes triggered unexpected re-renders, requiring manual optimization with $derived.by or breaking components into smaller pieces.

Scaling Svelte 5 to 50 Developers

Large teams need guardrails. We implemented several practices to keep our codebase consistent:

  • Shared component library: We built an internal Storybook-documented component library with 80+ Svelte 5 components, used across all our apps.
  • Strict style guide: Enforced rules like no $effect for derived data, $props rune for all component inputs, and max 200 lines per component.
  • Testing standards: All components use @testing-library/svelte and Vitest, with 85% code coverage required for new features.
  • CI/CD checks: We added Svelte compiler error checks, bundle size limits (max 200KB gzipped per app), and accessibility tests to our pipeline.

Lessons Learned

Two years in, these are our top takeaways:

  • Only use $effect for side effects (e.g., API calls, DOM manipulations) – 90% of your logic should use $state and $derived.
  • Use $props rune consistently instead of legacy export let patterns, even for internal components.
  • Monitor bundle size closely: Svelte’s small core means you can add dependencies without bloating, but it’s still easy to over-import.
  • Contribute to the community: We open-sourced 3 internal Svelte 5 utilities, and the maintainers were quick to respond to our bug reports.

Would We Do It Again?

Absolutely. For our use case – high-performance SPAs with frequent feature updates – Svelte 5’s developer experience and performance benefits far outweigh the ecosystem gaps. We’d advise large teams considering Svelte 5 to:

  • Start with a small, low-risk app to pilot the framework.
  • Invest in team training early, especially around runes mental models.
  • Build shared tooling (component library, testing utils) before scaling to all apps.

Svelte 5 has evolved rapidly over the past two years, with major improvements to reactivity, tooling, and ecosystem. We’re excited to see where the framework goes next, and we’re not looking back to React anytime soon.

Top comments (0)