⚡ LIVE From Lizard to Wizard · Thursday, May 28 · LIMITED SEATS Save my seat →
Episode 33 55 minutes

Frontend Foundations at Scale with Giorgio Polvara

Key Takeaways from our conversation with Giorgio Polvara

Giorgio Polvara

Staff Engineer at Perk (formerly TravelPerk), Frontend Foundations Builder

Señors @ Scale host Neciu Dan sits down with Giorgio Polvara, Staff Engineer at Perk (formerly TravelPerk), who joined when the company was 15 people in two flats with a hole knocked through the wall and helped build the frontend foundations that still hold up at unicorn scale. Giorgio covers the multi-year migration from a monolithic frontend to vertical micro-frontends, why their first attempt with single-spa didn't work, how they pulled off a full rebrand behind feature flags without leaking, and the staff engineer mindset of treating every feature as a system improvement.

🎧 New Señors @ Scale Episode

This week, I spoke with Giorgio Polvara, Staff Engineer at Perk (formerly TravelPerk). Giorgio has been writing code for nearly 20 years — starting with PowerPoint quizzes at 12, Turbo Pascal at 14, and a summer of jQuery and Adobe Flex working at his father's software studio in Italy. He joined TravelPerk when it was 15 people in two flats in Raval with a hole punched between them, and helped build the frontend foundations that now serve a unicorn with 1,800 employees globally.

In this episode, we go deep on the multi-year migration from a monolithic frontend to vertical micro-frontends, why their first attempt with single-spa didn't fit, how they pulled off a full company rebrand behind feature flags without leaking the design, and what the staff engineer role actually looks like across tribes.

⚙️ Main Takeaways

1. From PowerPoint quizzes to Staff Engineer at a unicorn

Giorgio's path into engineering started with a teacher showing him you could put buttons in PowerPoint slides.

  • The spark: At 12, his teacher showed the class that buttons in PowerPoint could jump to different slides. He started building four-button quizzes — one wrong answer slide, three right ones — and decided then he wanted to work with computers.
  • The first real code: Turbo Pascal at 14. Two variables, sum them, print "The sum is 10." He copied the code, hit compile and run, and was hooked.
  • The jQuery moment: At 16, someone showed him jQuery — click a button and a whole div disappears in one line of code. "That was an initiation for many." Debugging meant alert() calls because there was no inspector yet.
  • The Flex side gig: At his father's 8-10 person software studio, his job was studying things nobody else had time to study. One client wanted bubble sounds on button hover before the audio tag existed — Giorgio built it with embedded Adobe Flex.

2. Joining TravelPerk at 15 people through a Slack channel

The job that built the foundations was found on a local JavaScript meetup Slack.

  • The find: After moving to Barcelona for a conference, Giorgio looked for work in the Barcelona JS Slack channel. TravelPerk had a posting.
  • The office: Two flats in Raval with a hole knocked through one wall to connect them. 15 people total.
  • The growth: "Every day there is something new. Every day there are some changes." From standing standups to two-team standups to multiple offices to a tribe structure. The constant: nothing stays the same long enough to get used to it.
  • The takeaway: Once you're in hyper-growth, you stop noticing it. You only see the seams when you look back.

3. Code quality during hyper-growth: alternate, don't allocate

Giorgio doesn't believe in the "20% time for refactoring" model.

  • The reality: Different departments pull in different directions. Product wants new features. Engineering wants to fix the code. Finance wants to spend less. That tension is normal — leadership decides which way to lean each cycle.
  • The pattern: Tight deadline incoming → take on technical debt deliberately → ship the feature → validate in production → come back and fix the corners cut. Alternate periods of high feature velocity with periods of cleanup.
  • The mindset shift: "I'm a strong believer in the idea that you are not creating a feature — you're improving your system, and the by-product is also a new feature." Reframe every ticket as system improvement first, feature second.

4. Why the first micro-frontend attempt with single-spa failed

The horizontal split looked clean on paper but produced messy boundaries in production.

  • The problem they were solving: The frontend was becoming impossible to work in. Local dev server compiles long enough to "go get a coffee." A single broken test in CI blocked everyone's deploys. Teams kept stepping on the same files because there was no clear boundary separation.
  • The first attempt: single-spa — a router running in the browser deciding which micro-frontends to mount/unmount based on path. A horizontal client-side merge.
  • The failure mode: No real boundary separation. One CSS bug had a micro-frontend unmounting and accidentally stripping all the styles on the page when navigating away. Complexity was still very high.
  • The other constraints: single-spa was webpack-only at a time when they wanted to experiment with Vite. Roadmap features they needed had unclear timelines, and they didn't have the capacity to fork.

5. The vertical split that actually worked

Each micro-frontend became its own single-page application.

  • The architecture: A server-level JavaScript function looks at the path and routes to the appropriate micro-frontend. Visit /flights, get the flights micro-frontend served as its own SPA.
  • The mental model: "If you work in the flight squad, you can just pretend you are building an application to search flights. That's it. The rest of the world doesn't exist." No worrying about authentication or payment — just redirect to another page.
  • The trade-off: A full page refresh when crossing micro-frontend boundaries. Acceptable because users complete a flow inside one micro-frontend before jumping to another.
  • The result: Squads that estimated tickets at four days started shipping them in one. They stopped getting blocked by other teams.
  • The next step: Investigating service workers for asset pre-caching, API call caching, and the View Transitions API to make jumps imperceptible.

6. How the monorepo enforces a single stack across micro-frontends

Freedom to experiment, but with clear gravity toward the standard.

  • The setup: All micro-frontends live in one monorepo with pnpm + syncpack. Install a different version than the rest of the system and it yells at you. Exceptions are possible but not the default.
  • The Vite plugin: The Vite config for every micro-frontend is one line that calls a shared plugin. Want to change how assets are handled platform-wide? Modify the plugin once and every micro-frontend gets it.
  • The social contract: Teams can experiment with different stacks (one tried Next.js), but the Foundation Tribe doesn't support unsupported choices. Some experiments get adopted as the official stack — they just migrated from Jest to Vitest because it's faster with a similar API. Some get abandoned (Next.js).
  • The acquisition wrinkle: When they acquired a company with an Angular app, they embedded it as a micro-frontend — their architecture treats anything that emits HTML as valid. Shared components like navigation got rewritten as Web Components to bridge React and Angular until they finished rewriting the acquired app in React.

7. Tribes, squads, and how Perk adapted the Spotify model

Cross-functional teams owned by business domain, not by technology.

  • The structure: Tribes started from the Spotify model and got adapted. Tribes are organized by business domain — onboarding, booking, platform. Inside each tribe, multiple squads (e.g., flights, hotels) own their domain end-to-end.
  • The composition: Each squad has backend, frontend, full-stack, a dedicated designer, and a PM. They discuss with leadership, get quarterly approval, and ship without back-and-forth resource requests.
  • The naming: "I find it weird that every company names this thing differently. Some call it tribes, some clusters, some communities."

8. Pulling off a full rebrand behind feature flags without leaking

Last year Perk changed name, domain, logo, font, spacing, and color system — all live in production behind flags.

  • The constraint: The new design could not leak ahead of the marketing announcement. So the team built the new version using fake colors and fake logos until the very last moment.
  • The hard part: The design system existed but wasn't used everywhere — large parts of the app pre-dated it. They went page by page checking what broke.
  • The implementation: A hook decided whether to apply old or new styles. For small things (different margins) — if (hook) { newMargin } else { oldMargin }. For components that looked completely different, a shell component picked between an old version and a new version.
  • The cleanup: Once the flag was switched, finding all usages of the deprecated hook plus TypeScript flagging "this condition is always true" made cleanup straightforward.
  • The cultural piece: They ditched the regular sprint cycle for a few months. Created a task force. Opened the new rebrand to every Perk employee internally — anyone could flag bugs in Slack or Forma. "This idea of 'if you see something, say something' caught so many bugs because everyone in the company was looking at it."
  • The outcome: Big change, smooth release. A couple of misaligned pages, fixed quickly. "I was surprised. Usually you have a lot of issues with this kind of stuff."

9. CSS migration: from styled-components to CSS Modules with CSS Variables

The migration piggybacked on the rebrand work.

  • The why: styled-components is in maintenance mode. No advantage in staying.
  • The migration target: CSS Modules across the design system and a big chunk of the application.
  • The bonus: Used the migration to introduce CSS Variables. Design tokens that lived as JavaScript values became actual CSS variables, unlocking dynamic theming and runtime updates.

10. CI that scales with micro-frontends and a shared design system

The CI pipeline figures out what changed and runs only what's needed.

  • The setup: The Foundation tribe owns one CI pipeline used by every team.
  • The first step: Detect changed files. Modified one micro-frontend? Run only its tests. Modified the design system package? Run its tests plus tests for every micro-frontend that uses it.
  • The automatic version policy: Micro-frontends always use the latest version of internal packages automatically. Update the design system, and everything redeploys.
  • The mindset: "It sounds a bit scary. But if you start doing it a lot and you add monitoring, it just becomes second nature."

11. Schema validation in production with Zod

Early-stage experiment to catch API drift without breaking users.

  • The current model: Define the response type in TypeScript. That's it. No runtime check.
  • The Zod experiment: Define the response shape in Zod. Validate the actual response asynchronously after rendering. If it doesn't match, alert the on-call engineer.
  • The reasoning for async: "We don't want a customer to get a blank page because we did something wrong." Most schema drift is harmless — number arrives as a stringified number, code keeps working. Just want to know about it.
  • The composability: From the Zod schema you derive the TypeScript types. They also have a library called Fabricator that generates test data — soon, that data will come from the same Zod schema. Schema as source of truth.
  • vs PACT contract testing: Not a replacement. PACT validates workflow sequences ("user does X, API returns Y"). Zod validates response shape. Different layers, both useful. "When you do tests and quality assurance, you want different layers. The more layers you have, the less bugs go through."

12. Becoming a manager taught him he wanted to stay an engineer

A year as Engineering Manager at Toptal clarified his career direction.

  • The Toptal stint: Hired explicitly as Engineering Manager after doing some EM work as a side responsibility at TravelPerk. Wanted to take it on as a career.
  • The imposter syndrome: Wanted to do a good job, didn't know if he could. Eventually relaxed, got good feedback from his reports, and learned why managers ask for estimates (because the quarter has to be planned).
  • The realization: "I don't like this thing of having to evaluate a person every quarter and talk about promotion. It's a kind of pressure I don't enjoy." A year away from coding made him realize how much he missed it.
  • The frustration we shared: Being a manager and having no real power to promote someone — even when reviews said they exceeded expectations, leadership took the decision. "I felt I was just passing messages from one layer to another."
  • The return: He came back to TravelPerk as a Staff Engineer, where he could do architecture across tribes without being responsible for performance reviews.

13. The Staff Engineer role: impact and autonomy across tribes

The definition Giorgio uses at Perk.

  • Impact widens with seniority: Junior engineers know their squad's scope. Seniors understand their tribe's concerns. Staff engineers work across tribes — like leading the multi-year monolith-to-micro-frontends migration that affected every developer in the company.
  • Autonomy is the other axis: Juniors should ask questions all the time. "If you're a junior, don't be afraid of asking questions. It's exactly what I'm expecting of you." Staff engineers are the ones answering — they get a problem, analyze it, propose a solution on their own.
  • The career advice: To go from senior to staff, find problems outside your squad and tribe. Identify them, analyze them, propose solutions. "I would propose five different proposals and if I'm lucky one is picked up." Then implement, measure, iterate.
  • The non-technical skill: How you present the proposal matters. Engineers want libraries, CI, technical detail. Stakeholders want money, revenue, time saved. "That becomes increasingly important as you progress in your career — convincing people that your idea makes sense."

🧠 What I Learned

  • TravelPerk's frontend foundations were built when the office was two Raval flats connected by a hole in the wall and the team was 15 people.
  • During hyper-growth, alternate phases of feature debt with phases of cleanup. Don't allocate a fixed 20% for refactoring — treat every feature as system improvement first.
  • The first micro-frontend attempt at Perk used single-spa with a horizontal client-side split. It failed because boundaries weren't actually separated and complexity stayed high.
  • The vertical split — each micro-frontend as its own SPA, server-side path routing — works because each squad can pretend the rest of the platform doesn't exist.
  • Squads that estimated tickets at four days started finishing them in one after the migration.
  • A monorepo with pnpm + syncpack enforces a single stack while still allowing experimentation.
  • Vite config as a shared plugin lets you change platform-wide build behavior in one place.
  • Acquiring a company with an Angular app? Embed it as a micro-frontend and bridge shared components with Web Components.
  • A company-wide rebrand can ship behind feature flags without leaking — use fake colors during dev, switch them at the last moment, open the flagged version internally so everyone hunts bugs.
  • styled-components is in maintenance mode. Migrate to CSS Modules and use the opportunity to introduce CSS Variables.
  • CI should detect what changed and run only what's needed. Internal packages should auto-bump to latest.
  • Zod async response validation in production catches API drift without breaking users on schema mismatches.
  • PACT and Zod schemas validate different things. Use both — defense in layers.
  • A year as Engineering Manager taught Giorgio he prefers being a Staff Engineer working across tribes to evaluating reports each quarter.
  • Staff Engineer = impact across tribes + autonomy. The path: find problems outside your squad, propose solutions, present them in the language of the audience.

💬 Favorite Quotes

"Every day there is something new. Every day there are some changes. You start with we're all literally in the same room having a stand-up standing — to splitting two teams because the stand-up is just taking an hour."

"You are not creating a feature — you're improving your system, and the by-product is also a new feature. If you apply this mindset, it becomes much easier to maintain the system because it's your primary goal."

"If you work in the flight squad, you can just pretend that you are building an application to search flights. That's it. The rest of the world doesn't exist."

"It sounds a bit scary. But if you start doing it a lot and you add monitoring, it just becomes second nature."

"When you do tests and quality assurance, you want different layers. You don't want to have one thing that tests the thing. The more layers you have, the less bugs go through."

"If you're a junior, don't be afraid of asking questions. It's exactly what I'm expecting of you."

🎯 Also in this Episode

  • Bubble sounds on button hover for an Italian restaurant website — built with Adobe Flex before the audio tag existed
  • The Google Photos clone he built with a colleague in early 2000s, sending JavaScript values to the PHP backend session because he couldn't find them in the frontend
  • The Angular 2 rewrite era that pushed many companies (including TravelPerk) toward React around 2016
  • Going from full-stack at a Ruby on Rails + Angular fintech to specialized frontend because nobody else liked frontend
  • Why a hook is better than duplicate components for feature-flagged migrations — TypeScript helps clean up after deprecation
  • Internal Slack and Forma channels for company-wide bug reporting during the rebrand
  • Backend stack at Perk: Python + Django, with a growing amount of Lambda functions
  • Their internal design library "suitcase" used across all micro-frontends
  • Why they don't auto-generate React Query hooks from OpenAPI specs (yet)
  • The Fabricator library for generating test data — and the plan to drive it from Zod schemas
  • Why architecture must stay malleable: "Last two years we changed the name, the domain, the logo, everything. You just have to expect that things are going to change."

Resources

More from Giorgio:

  • Perk — formerly TravelPerk, the business travel unicorn
  • single-spa — the micro-frontend router they tried first
  • Vite — the build tool they migrated to from webpack
  • Vitest — their test runner, migrated from Jest
  • Zod — runtime schema validation library
  • PACT — contract testing framework
  • pnpm + syncpack — monorepo package management

Books mentioned:

🎧 Listen Now

🎧 Spotify
📺 YouTube
🍏 Apple Podcasts

Episode Length: 55 minutes on micro-frontends, monorepo architecture, surviving a rebrand behind feature flags, and the staff engineer mindset of treating every feature as a system improvement.

If you're scaling a frontend past the point where everyone can stand in one room, considering a monolith-to-micro-frontend migration, or trying to figure out what the staff engineer role actually means in practice, this conversation is for you.

Happy building,
Dan

🏆 SOLD OUT IN SINGAPORE · ATHENS · LONDON

From Lizard to Wizard

4-hour remote system design intensive.
Chat apps, microfrontends, BFF, SDUI, event-driven, observability.

€299 4-HOUR INTENSIVE
Save your seat →

Spots are vanishing. Don't be the one who waited.

💡 More Recent Takeaways

React Native at Scale with Kadi Kraman
Episode 35

Señors @ Scale host Neciu Dan sits down with Kadi Kraman, software developer at Expo working on the tools that make React Native development as smooth as possible. Kadi's path started with C++ in a university maths degree, took her through Angular 1, scientific programming for pharmaceutical and defense companies, five and a half years at Formidable, and finally to Expo itself. From the limitations of early React Native to development builds, EAS workflows, fingerprint-based repacks, and the right way to think about over-the-air updates, this is the React Native conversation most web developers never get.

Browser ML at Scale with Nico Martin
Episode 34

Señors @ Scale host Neciu Dan sits down with Nico Martin — open source ML engineer at Hugging Face working on Transformers.js, and Google Developer Expert in AI and web technology — to go deep on running machine learning models directly in the browser. Nico breaks down architectures vs. weights, quantization, tokenizers, ONNX, WebGPU, and why on-device AI is the right answer for a huge class of problems. He also shares the road from ski instructor and self-taught web developer to landing what he calls his dream job at Hugging Face.

Module Federation at Scale with Zack Chapple & Nestor
Episode 32

Señors @ Scale host Neciu Dan sits down with Zack Chapple, CEO and co-founder of Zephyr Cloud, and Nestor, the platform engineer building it, to go deep on module federation, microfrontends, and what it actually takes to go from code to global scale in seconds. They unpack why module federation is Docker for the frontend, how Zephyr composes applications at the edge in 80 milliseconds, and why the real unlock for enterprise teams isn't deployment — it's composition.

Service Mesh at Scale with William Morgan
Episode 31

Señors @ Scale host Neciu Dan sits down with William Morgan, CEO of Buoyant and creator of Linkerd — the world's first service mesh and a graduated CNCF project. William's path runs from teaching himself BASIC on a begged-for DOS PC, through Twitter's painful migration off Ruby on Rails into JVM-based microservices, and into building the proxy that handles retries, mTLS, load balancing, and multi-cluster traffic for thousands of production Kubernetes clusters. From the Scala-to-Rust rewrite to why every sustainable cloud native open source project needs a commercial engine behind it, this is the infrastructure conversation most application developers never get to have.

📻 Never Miss New Takeaways

Get notified when new episodes drop. Join our community of senior developers learning from real scaling stories.

💬 Share These Takeaways

Share:

Want More Insights Like This?

Subscribe to Señors @ Scale and never miss conversations with senior engineers sharing their scaling stories.