Engineering Blog

Zero-Copy Migration: How Yelp Moved Its Cassandra Fleet Between Kubernetes Clusters

Introduction How do you move a large Cassandra fleet of around 1000 Kubernetes Pods and a petabyte of data across Kubernetes clusters without anyone noticing? Apache Cassandra powers many of Yelp’s core features, from user profiles to ads and search. We run it on Kubernetes, orchestrated by a custom operator covered in our earlier blog post. When Yelp migrated its Kubernetes control plane to Amazon EKS, most workloads moved over seamlessly, but Cassandra was left behind on our legacy self-managed clusters alongside its persistent EBS-backed storage. The conventional way to move Cassandra between clusters is to stream the data: add...

Continue reading

The making of the Yelp Assistant UI

As simple as it may look, a chat application is made up of thousands of small decisions that we make along the way, all with the goal to build a delightful experience for users. But each decision comes with a cost, often paid in time. If you ask people to draw a chat application, there is a high chance that every drawing will look very similar to this. Yelp Assistant is the first large-scale consumer-facing use of large language models at Yelp. We built it to connect users with local professionals with a simple proposition: a user has a problem,...

Continue reading

ML based ranking using Nrtsearch

We’ve extended Nrtsearch with the Inference Plugin, which embeds ML-based ranking directly in the search layer — eliminating the need for a standalone scoring service. We use Nrtsearch (read more information on the blog post), a Lucene-based open-source search engine built by Yelp, to power a variety of applications such as business search, reviews search, ad delivery and photo search. In this blog post, we give a high-level overview of the Machine Learning (ML) based scoring workflow in Nrtsearch. We’ll show how ML models are configured and loaded, and how different applications use custom business logic to develop, test, and...

Continue reading

Building Menu Vision: Real-Time Dish Recognition

Menus aren’t just lists, they’re a window into a restaurant’s unique offerings, specialties, and personality, shaping where and what we choose to eat. But here’s the challenge: reading “Kung Pao Chicken - Stir-fried chicken with peanuts in spicy sauce” doesn’t tell you what the portions look like, whether other diners loved it, or if it matches your expectations. At Yelp, we knew we had the solution sitting in our user-generated content: hundreds of millions of photos, reviews, and prices for dishes. The problem? Users had to manually search for each dish, an experience that doesn’t work well when you’re at...

Continue reading

Migrating a Large Flow Monorepo to TypeScript

In early 2017, Webcore selected Flow as Yelp’s next-generation typechecker over TypeScript. At the time there was no clear frontrunner. Flow had better support for React, better performance, and a respectable repository of types for NPM packages in flow-typed. However, a few years later the landscape had shifted, and it became clear that TypeScript was emerging as the stronger choice. TypeScript’s DefinitelyTyped repo had thousands more packages than flow-typed, and many more packages shipped with built-in TypeScript headers. TypeScript also proved to be more stable over time, and limited uptake in the wider JS community made finding tools and documentation...

Continue reading

Migrating from Apollo Tooling to GraphQL Codegen at Yelp

Introduction At Yelp, we rely heavily on GraphQL and Apollo for data loading in our frontend React monorepo. When a developer writes a GraphQL query or mutation inside a React component, the shape of the response is defined by the query itself — but TypeScript has no way to know what that shape looks like at compile time. That’s where code generation (codegen) comes in. We rely on codegen to read our queries and server schema, then produce TypeScript type definitions for every operation’s input variables and output data. In our codebase, this looks like: src/components/UserProfile/ ├── UserProfile.tsx ← contains...

Continue reading

Training Orchestrator: Unifying Model Training at Yelp

At Yelp, we train many machine learning models on different schedules. Applied machine learning teams all have their own set of Spark-based training batches, scripts, and configurations. Over time, these diverged, leading to duplicated code, subtle inconsistencies, and a growing maintenance burden. Yelp’s Core Machine Learning Team has developed excellent tooling across our ML ecosystem over the years: feature stores for reproducible data, a unified training library for neural networks and gradient-boosted trees, seamless Spark integration, and MLflow services for model tracking and deployment. But there was still one key piece missing right in the middle: a standardized way to...

Continue reading

Beyond the Menu Tree: How Yelp Built a Smarter Customer Success Chatbot with AI

The Evolution of Support: From Fixed Phrases to Conversation At Yelp, delivering responsive and accurate customer support is a core priority. For years, our legacy Customer Success (CS) Chatbot provided support by guiding users through a static support experience. Users either navigated a 2-step menu tree or typed a query that was matched against a fixed set of phrases to retrieve an answer. While functional, the legacy chatbot had a key limitation: its reliance on rigid matching meant that if a query didn’t fit the menu structure or precisely match a known phrase, the user wouldn’t be able to get...

Continue reading