<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Expedia Group Technology - Medium]]></title>
        <description><![CDATA[Stories from the Expedia Group Technology teams - Medium]]></description>
        <link>https://medium.com/expedia-group-tech?source=rss----38998a53046f---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Expedia Group Technology - Medium</title>
            <link>https://medium.com/expedia-group-tech?source=rss----38998a53046f---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 16 Jun 2026 20:41:43 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/expedia-group-tech" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[The Most Expensive Milliseconds Are Unmeasured]]></title>
            <link>https://medium.com/expedia-group-tech/the-most-expensive-milliseconds-are-unmeasured-d6cfaaca881d?source=rss----38998a53046f---4</link>
            <guid isPermaLink="false">https://medium.com/p/d6cfaaca881d</guid>
            <category><![CDATA[time-to-interactive]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[observability]]></category>
            <category><![CDATA[performance]]></category>
            <category><![CDATA[devops]]></category>
            <dc:creator><![CDATA[Divya Gupta Arora]]></dc:creator>
            <pubDate>Wed, 03 Jun 2026 17:11:58 GMT</pubDate>
            <atom:updated>2026-06-03T17:11:56.743Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://medium.com/expedia-group-tech/subpage/engineering">Expedia Group Technology — Engineering</a></h4><h4>How a screen-level performance metric reshaped platform decisions, engineering ownership, and release discipline</h4><figure><img alt="People in row boats on the water with mountains in the background" src="https://cdn-images-1.medium.com/max/1024/0*2C2DF8u6MlbkeuC5" /><figcaption>Photo by Pietro De Grandi on Unsplash</figcaption></figure><p>For the last few years, my responsibility has been straightforward to state but hard to execute — <strong>owning the traveler login experience across mobile platforms</strong>.</p><p>Not just whether a feature works, but whether it <em>feels</em> responsive, predictable, and trustworthy in the moments that matter most. During login, those moments are unforgiving: if a login screen hesitates travelers don’t interpret it as ‘a slow render’, they interpret it as risk.</p><p>And when the majority of travelers interact through our mobile apps, performance stops being a technical concern and becomes a <strong>product promise</strong>.</p><p>This post is a case study of how, within <a href="https://www.expediagroup.com">Expedia Group</a>™’s login domain, we extended <strong>Native Time to Interactive (NTTI)</strong> across login screens — moving performance from a late-stage check to a first-class signal we can use to validate technology investments, compare platform behavior, and prevent silent regressions as we ship.</p><h3>The Problem: Mobile reliability rarely fails loudly</h3><p>Mobile performance rarely breaks with a crash.</p><p>It usually degrades quietly,</p><ul><li>a button takes a beat longer to respond</li><li>a screen <em>looks</em> ready, but taps don’t register</li><li>the UI stutters just enough to feel “off”</li></ul><p>Those are the expensive milliseconds — because they erode trust without triggering obvious alarms.</p><p>In our login flows, we were shipping consistently, evolving a major part of our stack, and supporting increasing product complexity. Yet we didn’t have a consistent way to answer the user’s real question — <strong>“When can I actually use this screen?”</strong></p><h3>Why our existing signals failed</h3><p>We were not blind. We tracked many useful things,</p><ul><li>crashes and ANRs</li><li>backend latency and service SLIs</li><li>some component-level timing signals</li><li>limited <a href="https://developer.mozilla.org/en-US/docs/Glossary/Time_to_interactive">Time to Interactive</a> tracking on onboarding and initial login</li></ul><p>But we had a gap — we had visibility into system health, not screen readiness.</p><p>Once travelers moved beyond the initial login screen into deeper login flows, performance became harder to compare release-to-release. We could detect obvious failures, but we lacked a consistent, screen-level metric that told us,</p><ul><li>Did this flow get slower after shipping feature X?</li><li>Did the new tech stack improve what travelers feel?</li><li>Are iOS and Android behaving similarly, or are we averaging away differences?</li></ul><p>And during a major tech stack migration, leadership asked fair questions — <strong>Are we actually delivering a better traveler experience ? Or just different architecture?</strong></p><p>We needed something more aligned with user-perceived readiness.</p><h3>What we chose to measure</h3><p>Expedia didn’t find an industry-standard metric that captured <em>native screen interactivity</em> the way Web Vitals capture <a href="https://developer.mozilla.org/en-US/docs/Web/API/LargestContentfulPaint">LCP</a> and <a href="https://developer.mozilla.org/en-US/docs/Glossary/Time_to_interactive">TTI</a> on the web. So we coined a native-inspired equivalent: <strong>Native Time to Interactive (NTTI)</strong>.</p><p><strong>Definition:</strong> <em>All components that are visible in the initial viewport are loaded and available for interaction.</em></p><p><strong>NTTI measures:</strong><br> The time from when the screen starts loading to when its key components have loaded.</p><h4>Key terms</h4><ul><li><strong>Screen Start:</strong> when a new screen starts rendering and the user can’t interact yet (user is effectively blocked)</li><li><strong>Key Components:</strong> essential UI components that must be ready for meaningful interaction (typically in the initial viewport)</li><li><strong>Last Key Component:</strong> when the final key component completes render and is ready for interaction</li></ul><h4>Formula</h4><p><strong>NTTI = Last Key Component − Screen Start</strong></p><figure><img alt="Diagram illustrating screen load process from load to usable state, highlighting key stages and user interactions. It uses colour-coded labels and icons to show timeline from screen start to readiness, including components loading, tap failures, and successful tap, with total measured time of 8 seconds." src="https://cdn-images-1.medium.com/max/1024/1*FlRYf9a5EZjfDPsDlErQRA.png" /><figcaption>What is Time to Interactive wrt native devices</figcaption></figure><h4>How we instrumented NTTI across login screens</h4><p>Performance instrumentation wasn’t absent before — but it wasn’t consistent across the login journey.</p><p>We had:</p><ul><li>component-level signals on both platforms</li><li>limited screen-level visibility on a few launch flows</li><li>gaps across deeper login screens</li></ul><p>Extending NTTI across login screens required more than “adding timers.” We had to make deliberate decisions.</p><h4>Why NTTI worked for us</h4><p>NTTI anchors to a human outcome:</p><p><strong>A screen isn’t “fast” when it renders. It’s fast when it responds.</strong></p><p>A screen that draws quickly but doesn’t respond to touch feels broken. A slightly slower screen that responds reliably feels fast.</p><p>NTTI helped us measure what travelers actually experience: <strong>readiness to interact</strong>, not just rendering completion.</p><h3>The work broke down into four steps</h3><h4>1. Define “interactive” from a traveler perspective</h4><p>We aligned on what “usable” means for each screen — not in theory, but in practice.<br>This forced healthy product + engineering conversations: what’s essential vs what’s nice-to-have.</p><h4>2. Choose key components per screen</h4><p>We selected a subset of components that represent real readiness.<br>Not every UI element should gate interactivity; if everything counts, NTTI becomes noisy and less actionable.</p><h4>3. Standardize measurement across platforms</h4><p>We ensured the measurement approach was comparable across iOS and Android even though runtime behavior differs.</p><h4>4. Make the data reliable enough for decisions</h4><p>A metric is only useful if people trust it. That meant validating instrumentation, watching for gaps, and ensuring consistency across releases.</p><p>This wasn’t just observability work. It was building <strong>an operational contract</strong>: if we ship UI changes, we must be able to measure the impact.</p><figure><img alt="Diagram illustrating web page loading process with a timeline labelled “Time to Interactive.” It features three key points: “Screen Start” marked by a blue circle, an intermediate interaction point with a hand cursor over a form, and “Ready” marked by a green check, showing transition from loading to full interactivity." src="https://cdn-images-1.medium.com/max/1024/1*028mkpjglx8iMVPp0WxWSA.png" /><figcaption><em>NTTI captures when a screen becomes usable, not just when it finishes rendering.</em></figcaption></figure><h3>What we learned: iOS and Android are not symmetric</h3><p>One of the most important things NTTI made visible is what experienced mobile engineers already know, but organisations often ignore — <strong>iOS and Android behave differently even when the UI looks identical.</strong></p><h4>iOS issues often surfaced as</h4><ul><li>subtle UI delays</li><li>main-thread contention</li><li>strict lifecycle + rendering constraints</li></ul><h4>Android issues often surfaced as</h4><ul><li>device + OS fragmentation</li><li>OEM-specific behavior</li><li>hardware-dependent variance</li></ul><p>Before NTTI, it was easy to blend results and assume parity. After NTTI, we could see platform deltas clearly and evaluate them fairly.</p><p>The same backend and product flow could yield different NTTI uplift across platforms. That wasn’t a product inconsistency — it was platform behaviour and implementation nuance.</p><figure><img alt="Line graph comparing Android and iOS over time with fluctuating blue line representing data points against a background of coloured horizontal bands indicating different value ranges. Graph includes labels for time on x-axis and a smooth trend line option, highlighting variable trends and occasional spikes within a consistent range." src="https://cdn-images-1.medium.com/max/1024/1*SnQrmzjoE4TAwU9StWULtA.png" /><figcaption>Same backend. Same Feature. Different Experience.</figcaption></figure><p>NTTI made those differences measurable instead of debatable.</p><figure><img alt="Line graph comparing performance data before and after improvements of Android over multiple days, with two distinct blue lines representing each period. The graph shows higher and more variable peaks before improvements and lower, more stable values after, highlighting a clear reduction in performance fluctuations." src="https://cdn-images-1.medium.com/max/1024/1*uPSdoCKsgAkzrq95-Q6ZAQ.png" /><figcaption>Before vs After performance improvements in Android (46.3% faster)</figcaption></figure><h3>The unexpected outcome: Better ownership</h3><p>One of the most valuable outcomes had little to do with the metric itself.</p><p>Once NTTI was introduced, teams naturally started to</p><ul><li>instrument what they shipped</li><li>read dashboards with intent instead of curiosity</li><li>connect code changes directly to traveler experience</li><li>identify and fix regressions earlier in the cycle</li></ul><p>Observability stopped feeling like a downstream activity. It became a core engineering discipline. And because the metric reflected real user experience, performance stopped being “just an engineering concern.” It became a shared responsibility. Product teams aligned on performance as a release guardrail and part of the user experience discussion. Design helped define what “ready” actually meant from an interaction standpoint. Engineering made those expectations measurable and actionable.</p><p>Over time, ownership shifted from <em>“Someone will catch this later.” </em>to <em>“If I ship it, I monitor it.” </em>That kind of cultural shift is difficult to enforce top-down.<br>NTTI helped create it through consistency, visibility, and repeated feedback loops.</p><h4>How this changes release conversations</h4><p>Today, NTTI is one of the first signals I look at</p><ul><li>before features ramp to wider production</li><li>while validating major technical initiatives</li><li>during release readiness discussions</li></ul><p>We haven’t yet fully adopted NTTI as a formal rollout blocker, but that’s the direction we’re moving toward.</p><h4>What we intend to do next</h4><ul><li>Treat NTTI degradation as a “pause and investigate” signal</li><li>Require explicit conversations before ramping when performance moves outside expected thresholds</li><li>Protect hard-earned performance gains from slowly regressing over time</li></ul><p>To be clear, NTTI won’t be the only release signal, but it will become an important guardrail because it forces the right conversations to happen early, while fixes are still practical and inexpensive.</p><h3>What NTTI tells us — and what it doesn’t</h3><p>Being explicit about scope has helped us use the metric responsibly.</p><h4>What we know</h4><ul><li>NTTI measures screen readiness from an interaction perspective</li><li>the same change can yield different outcomes across platforms</li><li>it works as an early regression guardrail</li><li>it improves release conversations through concrete signals</li><li>it increases engineering ownership of performance</li></ul><h4>What we don’t claim</h4><ul><li>NTTI doesn’t explain user intent or behavior</li><li>it isn’t used in isolation</li><li>it doesn’t prove causality beyond what it measures</li><li>platform parity is not assumed or enforced</li></ul><h3>Closing thought</h3><p>NTTI didn’t just provide another metric, instead it gave us</p><ul><li>earlier visibility into traveler friction</li><li>a concrete way to validate tech stack investments</li><li>a growing culture of engineers owning performance</li><li>a shared language for cross-platform performance conversations</li></ul><p>During login where trust, speed, and reliability are inseparable this discipline matters. Performance isn’t something we optimize later. With NTTI, it’s something we design for from day one.</p><p><a href="https://careers.expediagroup.com/life/">Learn about life at Expedia Group</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d6cfaaca881d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/expedia-group-tech/the-most-expensive-milliseconds-are-unmeasured-d6cfaaca881d">The Most Expensive Milliseconds Are Unmeasured</a> was originally published in <a href="https://medium.com/expedia-group-tech">Expedia Group Technology</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Just Because We Can Build It, Should We?]]></title>
            <link>https://medium.com/expedia-group-tech/just-because-we-can-build-it-should-we-a292fbdd22ce?source=rss----38998a53046f---4</link>
            <guid isPermaLink="false">https://medium.com/p/a292fbdd22ce</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[platform]]></category>
            <category><![CDATA[engineering-leadership]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <dc:creator><![CDATA[Rick Fast]]></dc:creator>
            <pubDate>Tue, 05 May 2026 11:01:02 GMT</pubDate>
            <atom:updated>2026-05-05T11:01:01.694Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://medium.com/expedia-group-tech/subpage/platform">Expedia Group Technology — Platform</a></h4><h4><strong>How AI changed the build vs. buy equation, and why discipline matters more than ever</strong></h4><figure><img alt="A hiker viewed from behind holding a compass, standing in an open landscape" src="https://cdn-images-1.medium.com/max/1024/0*H8MhgBKBcrZGZZEc" /><figcaption>Photo by Ali Kazal on Unsplash</figcaption></figure><p>Agentic coding tools and AI-native workflows have changed what’s possible for platform engineering teams. I lead Platform Engineering at <a href="https://www.expediagroup.com">Expedia Group</a>™, one of the world’s largest travel technology companies. We power brands like Expedia®, Hotels.com®, Vrbo®, Orbitz®, and Travelocity®. My organization builds the technology that all of these brands and their partners run on: APIs, data and AI services, developer tools, CI/CD infrastructure, and the shared capabilities that let thousands of engineers ship reliably at scale.</p><p>For many greenfield problems, it now feels like we can build almost anything from scratch with a fraction of the effort it used to take. But that creates a harder question: <strong>just because we can build it, should we?</strong></p><h4><strong>The temptation is real</strong></h4><p>When you lead a platform organization and your engineers suddenly have access to powerful agentic coding assistants, the possibilities open up fast. It’s tempting to look at SaaS products your company is paying for and think, “We could build that in a weekend.”</p><p>And honestly? In many cases, you probably could stand something up quickly. The initial build cost has dropped through the floor.</p><p>But building something and <em>owning</em> something are very different decisions. That’s where the new calculus gets interesting.</p><h4><strong>The hidden cost of owning software</strong></h4><p>Vendors aren’t just shipping features. They’re maintaining the software, fixing bugs and edge cases you haven’t thought about yet, and improving the UX across thousands of customers with different requirements. Mature platforms have decades of accumulated work behind them: production hardening, compliance, operational tooling, and long-tail requirements you’d only discover slowly through real-world use.</p><p>You can’t clone that maturity quickly, even if the initial build feels cheap thanks to AI. <strong>The build side of the equation has changed dramatically, but the own-and-operate side has not changed nearly as much.</strong></p><p>There are cases where the calculus does shift. Some products are undifferentiated and low value; they don’t justify ongoing spend when simpler alternatives exist. For those, it may make sense to stop paying and either build a lightweight replacement or simplify. But that’s a very different posture than “we can build everything now, so we should.”</p><h4><strong>Our AI platform strategy: what we actually did</strong></h4><p>Last year, we made an explicit strategic decision in our AI platform work: stop implementing everything from the ground up internally, and instead lean into composable, external building blocks.</p><p>We had previously built bespoke AI platforms in-house. Custom orchestration layers and gateways, proprietary memory systems, internal agent frameworks. They worked, but they came with heavy maintenance costs and, more importantly, they fell behind the pace of the broader AI ecosystem.</p><p>So we changed direction:</p><ul><li><strong>We adopted an AI platform architecture</strong> that uses open standards and vendor ecosystems, such as n8n and LangSmith, rather than proprietary abstractions.</li><li><strong>We simplified our LLM proxy layer</strong> by swapping in an off-the-shelf routing product (LiteLLM) instead of maintaining a fully custom implementation.</li><li><strong>We replaced our in-house agent memory system</strong> with a cloud-native composable alternative (such as AWS’s Agent Core memory), treating it as a pluggable component rather than another platform we’d have to run forever.</li></ul><p>The principles behind these moves:</p><ol><li><strong>Composability matters most.</strong> Our ecosystem is complex. We need building blocks that fit together cleanly across dozens of teams and product lines.</li><li><strong>Don’t abstract away vendor progress.</strong> The AI space moves extremely fast. If you build thick proprietary abstractions on top of vendor frameworks, you’ll always be behind their latest capabilities. You end up maintaining a translation layer instead of shipping value.</li><li><strong>Turnkey integrations, thin layers.</strong> Make integration easy and batteries-included, but don’t build heavy opinionated layers that freeze you in place.</li></ol><p>Since the pivot, teams have picked up new AI capabilities faster, we spend less time rebuilding what others already provide, and we can actually keep up with improvements from frameworks and vendors as they ship.</p><h4><strong>The broader lesson: what this means for platform teams</strong></h4><p>This applies well beyond AI platforms. As a platform engineering organization, building platform technology is our core job, and agentic tooling has made that a lot easier. But that doesn’t mean everything we <em>could</em> turn into a platform <em>should</em> become one.</p><p>If you over-platformize, you risk creating an internal marketplace of cool tech that isn’t aligned with near-term business goals and doesn’t have clear owners or long-term roadmaps. You anchor to local inventions that the broader industry doesn’t converge on, so you’re maintaining something proprietary while everyone else moves in a different direction. You raise the abstraction bar so high that teams can’t adopt new external capabilities when they emerge. In short: you can end up slowing your company down in the name of moving fast.</p><h4><strong>How we decide what to build</strong></h4><p>Here’s the framework we’re applying across Platform Engineering at Expedia Group.</p><h4><strong>Start from team priorities, not technical possibilities</strong></h4><p>Before building a new platform capability, ask: <em>What specific team priority does this support? What goals are we trying to achieve in the next 12–18 months? Is this the best use of time for those goals, or just an interesting technical opportunity?</em></p><h4><strong>Build for your own domain first</strong></h4><p>When you build, optimize for your domain problem: your runbooks, your incident patterns, your critical flows. Don’t pre-optimize for everyone else’s domains. Other teams now have access to the same AI building blocks and can solve their own problems. If your solution becomes obviously valuable and reusable, you can look at platformizing it later, deliberately.</p><p>A good mental check: <em>if this didn’t exist, would my team still have a hard, recurring problem next quarter?</em> If the answer is “not really,” it’s probably not where you should invest platform cycles.</p><h4><strong>Favor composable primitives over monolithic platforms</strong></h4><p>Across our AI and platform work, the primitives that are working best:</p><ul><li><strong>Skills</strong>: Small, composable chunks of procedural and domain knowledge. Easy to share across repos, tools, and teams without creating hard dependencies.</li><li><strong>API servers with standard protocols + CLI’s</strong>: Standardized ways to expose domain capabilities into agentic workflows. Model Context Protocol (MCP) is an open standard for connecting AI assistants to external tools and data, and it’s gaining real traction here. It works naturally for both coding and non-coding use cases.</li><li><strong>Agents designed for compatibility</strong>: Scoped to specific problem domains or workflows (CI/CD, incident response, deployment orchestration) and built to load the right skills and connect to the right services automatically.</li></ul><p>These are low-regret bets. They compose well with multiple tools and coding agents, stay close to open standards, and are easier to replace or upgrade than monolithic platforms.</p><p><strong>A concrete example</strong>: Picture a CI/CD agent that picks up work after a pull request is merged and handles higher-level deployment workflows: interpreting pipeline configurations, managing rollbacks, handling approvals, calling standardized deployment APIs. Back it with composable skills and protocol-compliant service integrations, and you get something that stays close to existing platform primitives, evolves as your deployment stack evolves, and can be adapted by other teams without hard-coding all logic into a single bespoke system.</p><h4><strong>The buy side: same discipline, different direction</strong></h4><p>This same calculus applies to vendor and purchasing decisions. In today’s AI market, lots of vendors want you to centralize all your data in their ecosystem and use their proprietary dashboards, agents, and knowledge graphs.</p><p>In a space moving this fast, that creates a different kind of lock-in. Not just with a product, but with your data, workflows, and mental model of how you operate. We’re cautious about all-or-nothing stacks that try to own the entire vertical and platforms that don’t let you swap components in and out.</p><p>Our preferred vendor pattern: <strong>composable offerings</strong> where we can plug a component into our stack, swap it out later if needed, and we’re not forced to centralize everything into a single closed ecosystem. We want the flexibility to adapt as the AI space shifts, because it will shift, repeatedly, and probably faster than any of us expect.</p><h4><strong>The bottom line</strong></h4><p>The calculus of build vs. buy is changing. AI and agentic tools have altered what’s possible and how quickly platform teams can move. But discipline matters more than ever.</p><p>Here’s what we’re telling our teams:</p><ol><li><strong>Keep innovating</strong>, especially on your own workflows. Anything that improves your team’s productivity or simplifies your day-to-day is worth doing, even if it never becomes a broad platform product.</li><li><strong>Be intentional about what you turn into shared platform tech.</strong> Ask what domain problem it solves repeatedly, whether it’s best expressed as a composable primitive, and whether it aligns with the goals you’ve already committed to.</li><li><strong>Stay close to open standards and vendor primitives.</strong> This keeps you compatible with the tools your engineers already gravitate toward and lets you pick up new capabilities as they ship.</li><li><strong>Don’t make yourself the bottleneck.</strong> Your job as a platform team is to amplify industry progress for your company, not get in the way with heavy bespoke platforms that age badly.</li></ol><p>Our competitors have these same capabilities now. The difference won’t be who can build the most. It’ll be who applies that ability most deliberately to the software that actually helps them win.</p><p><em>The author leads Platform Engineering at Expedia Group, where the team builds the technology platform powering travel for millions of people across Expedia, Hotels.com, Vrbo, and other brands worldwide.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a292fbdd22ce" width="1" height="1" alt=""><hr><p><a href="https://medium.com/expedia-group-tech/just-because-we-can-build-it-should-we-a292fbdd22ce">Just Because We Can Build It, Should We?</a> was originally published in <a href="https://medium.com/expedia-group-tech">Expedia Group Technology</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Expedia’s Service Telemetry Analyzer]]></title>
            <link>https://medium.com/expedia-group-tech/expedias-service-telemetry-analyzer-60f2f96c5351?source=rss----38998a53046f---4</link>
            <guid isPermaLink="false">https://medium.com/p/60f2f96c5351</guid>
            <category><![CDATA[observability]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[distributed-systems]]></category>
            <category><![CDATA[generative-ai-tools]]></category>
            <category><![CDATA[site-reliability-engineer]]></category>
            <dc:creator><![CDATA[Nikos Katirtzis]]></dc:creator>
            <pubDate>Tue, 28 Apr 2026 11:01:01 GMT</pubDate>
            <atom:updated>2026-04-28T14:34:36.576Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://medium.com/expedia-group-tech/subpage/engineering">Expedia Group Technology — Engineering</a></h4><h4>A system that facilitates investigation of service degradations and outages using service telemetry data and AI</h4><figure><img alt="Night view of the town of Naxos from the port. The town is brightly lit, with golden lights from the buildings reflecting on the rippling surface of the water. Several boats are docked near the shore on the right side of the image. The sky above is a deep blue." src="https://cdn-images-1.medium.com/max/1024/1*SIfYhK_UBv-1Hpf5f9WCNQ.jpeg" /><figcaption>Photo by Evangelos Mpikakis on Unsplash.</figcaption></figure><p>The recent advancements in the artificial intelligence space make us re-evaluate how work is done. From programming, to designing systems, or even operating them in production. While there is considerable focus on automating programming, one area which could undergo transformation is how we monitor and operate our systems and services.</p><p>A few of us came together and designed Expedia’s® Service Telemetry Analyzer (STAR), an early iteration of a system that facilitates investigation of service degradations and outages using service telemetry data and AI models and techniques.</p><figure><img alt="An illustration of a friendly-looking, blue robot with a square head and antennas. Above its head, there is a colorful bar graph and small, sparkling stars. The robot’s eyes are light blue, glowing rectangles, and its mouth is a simple, curved line. Below the robot, the word “STAR” is written in a bold, sans-serif font. The illustration is set against a faint background." src="https://cdn-images-1.medium.com/max/200/1*ZktmgcsaQ0BNLX0e5zdnOw.png" /><figcaption>Expedia’s Service Telemetry Analyzer (STAR)</figcaption></figure><p>The early product offering includes:</p><ul><li>Execution of multi-step workflows.</li><li>Integration of software and systems engineering knowledge, including application and infrastructure, cloud, containerization, and orchestration patterns, into diagnostic workflows for complex distributed systems.</li><li>Application of domain-specific prompt engineering for metric and root cause analysis.</li><li>Utilization of advanced off-the-shelf AI models.</li><li>Implementation of prompt engineering techniques, including r<a href="https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/system-prompts">ole prompting</a>, p<a href="https://www.promptingguide.ai/techniques/prompt_chaining">rompt chaining</a>, and g<a href="https://www.promptingguide.ai/techniques/knowledge">enerated knowledge prompting</a>.</li></ul><h3>Design</h3><p>The product offering is a web-based service that provides an application programming interface (API). While AI agents and chatbots are gaining traction, we aimed to start with something a) simple, b) precise (to a certain extent, considering the potential hallucinations of the models), and c) that avoids the additional and currently less understood failure modes of an agent. As this field evolves, we will continue to iterate on the design.</p><p>Therefore, there is limited <a href="https://www.philschmid.de/context-engineering">context engineering</a> beyond domain-specific prompts; for instance, there is no support for <a href="https://platform.openai.com/docs/guides/function-calling">function calling</a> / <a href="https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/overview">tool use</a>, short-term and long-term memory, or r<a href="https://en.wikipedia.org/wiki/Retrieval-augmented_generation">etrieval augmented generation</a> (RAG). The system provides vertical domain-specific workflows. It adheres to a predefined multi-step process, with an emphasis on automating scenarios encountered by our engineers and enhancing the system’s precision. If you are interested in tool use with <a href="https://modelcontextprotocol.io/introduction">model context protocol</a> (MCP) servers for software development, you can read more in my <a href="https://nikoskatirtzis.substack.com/p/experimenting-with-the-model-context">public blogpost</a>.</p><h4>Web service</h4><p>The architecture is relatively straightforward, comprising an API layer and a web server built with <a href="https://fastapi.tiangolo.com/">FastAPI</a>. This service manages requests to Expedia’s chosen metrics platform (Datadog) and to the internal generative AI proxy, including authentication/authorization.</p><figure><img alt="An image depicting the entire Web architecture behind STAR." src="https://cdn-images-1.medium.com/max/841/1*53CO5yvdodvqZiqh-VrhUQ.png" /><figcaption>Web architecture behind STAR</figcaption></figure><h4>AI models</h4><p>The service invokes models via Expedia’s generative AI proxy. The proxy offers access to different models which we constantly evaluate for quality of results, cost, and performance implications. We are also exploring using different models for the various tasks in STAR. The use of large language models (LLMs) for any tasks was convenient for the prototype but it would be more effective to use specialised models for the different modalities of telemetry data and slower reasoning models for the final <a href="https://en.wikipedia.org/wiki/Root-cause_analysis">RCA</a>.</p><h4>Prompt chaining</h4><p>Part of the implementation involves prompt chaining, which facilitates a programmatic dialogue between the user and the assistant.</p><figure><img alt="An image depicting the sequence diagram of prompt chaining; programmatic dialogue between the user and the assistant." src="https://cdn-images-1.medium.com/max/1024/1*cWtl1f6DlNceNjHEG0E5iQ.png" /><figcaption>Prompt chaining; programmatic dialogue between the user and the assistant</figcaption></figure><h4>Multi-step workflows</h4><p>Overall, STAR provides multi-step workflows, which are visualized below. In specific:</p><ol><li>It collects telemetry data.</li><li>It analyzes these metrics and the associated metadata using AI models and domain-specific prompts and rules.</li><li>It aggregates all analyses and conducts a final root cause analysis.</li><li>It returns insights and recommendations.</li></ol><figure><img alt="An image depicting a sequence diagram of Multi-step Reasoning Process implemented in STAR." src="https://cdn-images-1.medium.com/max/1024/1*_3Ewv4lVXwTmNacCEp9-fg.png" /><figcaption>Multi-step Reasoning Process implemented in STAR</figcaption></figure><h4>Ingested data</h4><p>The initial focus on observability metrics was on infrastructure components, with a particular emphasis on Kubernetes and JVM for two reasons: our heterogeneous tech stack and the higher degree of standardization at the infrastructure layer.</p><p>The default analyzer now ingests metrics including inbound and outbound traffic and errors, latency across various protocols like HTTP, gRPC, and GraphQL, and saturation monitored through container-level CPU and memory usage.</p><p>Additionally, the system ingests Kubernetes metrics, such as container restarts and probe failures, as well as JVM metrics for heap usage and garbage collection. This set of signals is tailored to our environment, where most services are backend JVM applications running on a Kubernetes-based compute platform.</p><h3>Implementation details</h3><p>While designing this system we faced a set of of interesting problems which may be useful to the reader.</p><h4>The nuances of token-heavy systems</h4><p>When we first designed STAR, LLM tooling was limited. Given STAR is a token-heavy system and in order to understand the feasibility and implications of this, we followed a systematic approach for back-of-the envelope estimation, grounded in facts, assumptions, and enforced limits.</p><p>We estimated the number of tokens using <a href="https://platform.openai.com/tokenizer">OpenAI’s GPT-4o tokenizer</a>. For this, we took into account any payload sent as context to the models. This included fixed-length prompts for system prompts and the chain-of-prompts, as well as prompts the length of which depends on previous responses. To control the number of tokens we capped each response to 4k tokens. This number was then used for estimation purposes.</p><p>Based on this analysis and the relatively static nature of the system, we concluded that we can accommodate the <a href="https://www.ibm.com/think/topics/context-window">context window</a> size. Note that this differs between models and has been increasing over time.</p><h4>Datadog and generative AI proxy limits</h4><p>Both Datadog and Expedia’s Generative AI proxy have rate limiting in place. Even though the scale is still small and the number of metrics per workflow is fixed, we accommodate these limitations using common resiliency patterns, while also leveraging asynchronous operations and batch processing.</p><h4>Architectural evolution</h4><p>This service is mostly I/O bound, but we still have synchronous operations. Each analysis is independent, yet we need to provide a response on the status of the analysis to the user. For this, we initially used certain features from FastAPI such as <a href="https://fastapi.tiangolo.com/async/">async/await</a> and <a href="https://fastapi.tiangolo.com/tutorial/background-tasks/">background tasks</a>. As part of scaling up, we moved to <a href="https://docs.celeryq.dev/en/latest/getting-started/introduction.html">Celery</a> with Redis acting as the broker and result backend to store the state and results of tasks. This architecture aligns with STAR’s request-response flow, and we don’t need a streaming platform like Kafka, at least for now.</p><h3>Use cases</h3><p>Numerous use cases could emerge for such a system. Below is a summary of how we have utilized STAR so far.</p><h4>Incident investigation</h4><p>The primary use case and the rationale behind the design of STAR. Our objective with this service was to minimize the time to know (TTK) and time to recover (TTR). By enabling rapid analysis of observability data and evaluation of hypotheses, this service proved to be a valuable time-saving tool. We applied STAR to several services that experienced outages.</p><h4>Post-incident root cause analysis</h4><p>Following an incident, teams file a ticket for post-incident review. By running STAR for the affected service(s) and the time-window of the incident, we can provide an initial analysis. This can then be reviewed and supplemented by human expertise.</p><h4>Troubleshooting</h4><p>Engineers spend a significant amount of time troubleshooting systems. Over time, Expedia’s reliability engineering group has documented troubleshooting steps in the company’s internal reliability hub. A logical step was to implement guides relying on metric data as workflows in STAR.</p><p>Our first addition was the process our engineers normally follow for troubleshooting container restarts in our Kubernetes-based compute platform. An indicative analysis result is available at <a href="https://gist.github.com/nikos912000/1e489021b406f682d70c14f3ebbad917">https://gist.github.com/nikos912000/1e489021b406f682d70c14f3ebbad917</a>.</p><h4>Performance optimization</h4><p>This is a recent use case that we are still evaluating. An Expedia service faced an issue where the JVM memory heap usage would suddenly spike. Such occurrences can be problematic; while container restarts can temporarily mitigate them, they expose long-standing issues that may lead to incidents.</p><p>Running STAR for this service provided a valuable analysis which was then reviewed and taken forward by the owners of the service.</p><h4>Failure injection recommendation and analysis</h4><p>Another idea involves recommending failures to inject and analyzing the impact of injected failures utilizing Expedia’s <a href="https://medium.com/expedia-group-tech/chaos-engineering-at-expedia-group-e51a0288ee2">chaos engineering platform</a>. When we developed this platform, we lacked a mechanism for the automatic evaluation of experimental results. STAR could serve as a complementary tool to this platform.</p><h3>Evaluation</h3><p>We are still in the early stages of evaluating the system. Given the complexity of this domain, we mostly rely on qualitative human assessment which includes subject matter experts (SMEs) and users. We also use <a href="https://langfuse.com/docs">Langfuse</a> for prompt management, evaluation, and tracing. The results so far have been promising.</p><h3>Next steps</h3><p>As we iterate through this early prototype, our emphasis is on identifying high-leverage use cases, improving testing and evaluation, and adapting to this rapidly evolving field. As it was mentioned earlier, this is still a static system rather than a sophisticated multi-agent architecture, lacking core elements of context engineering. It may benefit from tool use through MCP servers and from additional context such as service documentation, metadata, or the dependency graph of the targeted service. In the future we could also expose a conversational interface.</p><p>The initial concept and implementation of this project were proposed by <a href="https://medium.com/u/4aa892ba9ae9">Lasantha Kularatne</a> following discussions regarding recent advancements in the field of Artificial Intelligence and their application at the intersection of software and systems engineering. Also thanks to <a href="https://medium.com/@sundeepbhatia_90808">Sundeep Bhatia</a>, <a href="https://medium.com/@rahul.gupta395">Rahul Gupta</a>, <a href="https://medium.com/@gianpiero.colonna">Gianpi Colonna</a>, and <a href="https://medium.com/@kainee">Kaushik Patel</a>.</p><p><a href="https://careers.expediagroup.com/life/">Learn about life at Expedia Group</a>™</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=60f2f96c5351" width="1" height="1" alt=""><hr><p><a href="https://medium.com/expedia-group-tech/expedias-service-telemetry-analyzer-60f2f96c5351">Expedia’s Service Telemetry Analyzer</a> was originally published in <a href="https://medium.com/expedia-group-tech">Expedia Group Technology</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Reimagining Platform Engineering for an Agentic Future]]></title>
            <link>https://medium.com/expedia-group-tech/reimagining-platform-engineering-for-an-agentic-future-03e3f378a190?source=rss----38998a53046f---4</link>
            <guid isPermaLink="false">https://medium.com/p/03e3f378a190</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[platform-engineering]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[expedia-group-tech]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Rick Fast]]></dc:creator>
            <pubDate>Tue, 07 Apr 2026 12:50:31 GMT</pubDate>
            <atom:updated>2026-04-07T12:50:29.705Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://medium.com/expedia-group-tech/subpage/engineering">Expedia Group Technology — Engineering</a></h4><h4>When your platform’s next user isn’t human</h4><figure><img alt="Houses along the water" src="https://cdn-images-1.medium.com/max/1024/0*l3aHcuQMPu6Pc8W3" /><figcaption>Photo by Alex Vasey on Unsplash</figcaption></figure><p>Earlier this month I hosted a town hall for <a href="https://www.expediagroup.com">Expedia Group</a>™ Platform Engineering organization, focused on the rapid progress happening in the agentic coding space, and what it means for us as engineers and as a platform team.</p><p>Our teams are responsible for the horizontal foundations that power Expedia Group: AI and analytics, data, user experience platforms, edge and API platforms, cloud and infrastructure, as well as EG’s developer experience.</p><p>In other words, we own the “platform of platforms” that thousands of engineers build on every day.</p><p>Since late last year, with the arrival of models like Opus and modern deep agent harnesses, we’ve been riding a pretty intense wave of change. Larger context windows and more capable agents have made several things clear. A huge amount of what we call “engineering work” can now be done by agents. The real leverage for humans is shifting toward product thinking, architecture, system design, and context. Our platforms, which were designed for humans, are not yet ready to support agents as a distinct user group.</p><p>This post is about what it means to run a large‑scale platform organization in that world, and how we’re retooling our stack, our interfaces, and even our mental models to support both humans and agents at the same time.</p><h4>The change curve for senior engineers</h4><p>For many engineers, especially those who’ve been in the industry for decades, this isn’t just a new toolchain; it’s a <strong>new inner loop</strong>. We’re asking people to delegate more of the “typing” to agents, spend more time on <em>what</em> we’re building and <em>how it fits</em> into the larger system, and learn how to collaborate with agents as teammates, not just as autocomplete.</p><p>That would be hard enough in a greenfield startup. In a company that runs a large chunk of the online travel ecosystem, it’s even harder. We still must keep the planes in the air: keep sites up, pipelines flowing, and revenue‑critical systems healthy.</p><p>Finding the time and headspace to <strong>change how you work</strong> while you’re doing all of that is non‑trivial.</p><p>One experiment we ran to break through that inertia was something we called <strong>Ralphathon,</strong> a “no‑coding‑allowed” hackathon designed to encourage people to explore what these tools could do <em>without</em> falling back to old patterns. The goal wasn’t to build production‑ready projects; it was to spark curiosity, lower the barrier to experimentation, and give people a safe space to rethink their workflows.</p><p>It worked well enough to confirm a hypothesis: you can’t just <em>tell</em> people to change their inner loop. You have to create the right environment and incentives so they can <em>feel</em> the new way of working.</p><h4>Double duty: Transforming ourselves and the platform</h4><p>Platform engineering is on <strong>double duty</strong>.</p><p>On the one hand, we’re going through the same personal and professional shift as every other engineer: How do these tools change our careers? How do we work more efficiently, productively, and creatively? What does “senior engineer” mean in a world where agents can write most of the code?</p><p>On the other hand, we’re responsible for a platform that was originally built for humans. Expedia Group has been around for decades. Our architectural decisions were optimized around <strong>human constraints</strong>.</p><p>Take microservices. We didn’t split everything into tiny services because it was faster or cheaper. We did it so:</p><ul><li>Teams could deploy independently,</li><li>Work could be done autonomously, and</li><li>We didn’t have thousands of people all crowding into a single repo and stepping on each other’s toes.</li></ul><p>That all made sense in a human‑only world. But in an <strong>agentic</strong> world, some of those same decisions become friction: CI/CD flows that assume a human is in the loop, SDKs and libraries optimized for human ergonomics rather than agent ergonomics, and UIs that are the <em>only</em> way to perform certain critical operations. Our job now is to <strong>fast‑forward the platform</strong> beyond “SDKs + UIs + some APIs for humans” into something that works just as well, if not better, for agents.</p><p>And we must do that while supporting thousands of engineers who are also trying to navigate the same transition.</p><h4>How to Expedia, for agents</h4><p>A concrete example: our <strong>design system</strong>.</p><p>We’ve invested heavily in component libraries across iOS, Android, and web. They allow teams to build reusable modules without worrying about which consumer or B2B brands they’re targeting. The theming, styling, and look‑and‑feel are all handled by the platform. That’s a core capability for a multi‑brand travel platform, and it’s not going away.</p><p>But over time, we layered <strong>proprietary abstractions</strong> on top of standard tech: custom rendering frameworks on top of React, patterns and helpers that are unique to us, and other undifferentiated technology that only exists inside our walls.</p><p>Humans can learn those abstractions. Agents, on the other hand, were trained on the open ecosystem. They “just know” things like Vite, Tailwind CSS, and popular off‑the‑shelf UI libraries and patterns. When we ask an agent to work inside our design system, it can do it, but it doesn’t feel natural. The path of least resistance is to reach for the tools it understands best, which might be <strong>outside</strong> the guardrails we want it to stay within.</p><p>That’s the first kind of problem we must solve: not “How do we add more abstractions?” but “<strong>How do we remove unnecessary ones</strong> so both humans and agents can work with the same primitives more easily?”</p><h4>The hard part isn’t just writing code</h4><p>The second category of friction shows up <strong>after</strong> the code is written.</p><p>Even with current tools, we’re seeing clear gains in how much software can be produced in a given amount of time. Agents are extremely good at generating boilerplate and glue code, translating patterns across services and stacks, and filling in implementation details once the architecture is clear.</p><p>But there’s a lot that happens <strong>between</strong> “code compiles” and “value in production”, including deploying services, running CI/CD pipelines, monitoring workloads, and debugging integration issues across a highly distributed ecosystem.</p><p>Agents are ready and willing to help here, but we haven’t always given them a clean way in.</p><h4>AI finds a way (whether we like it or not)</h4><p>One of the more interesting (and slightly unsettling) things we’ve seen is how <strong>creative</strong> agents can be when you don’t give them proper interfaces. People have asked agents like Claude or others to “watch my pipeline” even when there is no standardized API or integration to do that. The only official way is through a web UI.</p><p>What happens?</p><p>The agent figures out how to log in through the browser, inspects cookies and session state, then navigates the UI as a human would, just faster and more persistently.</p><p>If there’s <em>any</em> way to accomplish the task, the agent will try to find it. From a platform perspective, that’s a signal: if you don’t give agents ergonomic, well‑defined interfaces, they’ll route around you.</p><p>We don’t want to block agents from doing useful work. But we also don’t want our critical operations mediated through brittle browser automation held together by HTML and guesswork.</p><p>So we’ve started to optimize for <strong>agent guardrails</strong>, not <strong>agent roadblocks</strong>.</p><h4>Designing for agent ergonomics</h4><p>This is where <strong>agent ergonomics</strong> becomes a core design principle. Instead of assuming a human is clicking around in a UI, we’re investing in <strong>channels and surfaces that are built for agents</strong> from day one. That includes:</p><p><strong>CLIs designed for agents, not humans<br></strong>We’re building command‑line tools whose primary consumers are agents. They are:</p><ul><li>Easy to introspect.</li><li>Consistent in their inputs and outputs.</li><li>Wired into the systems agents need to operate, including CI/CD, repo management, Kubernetes workloads, logs, and more.</li><li>If there’s a simple, well‑documented way to perform an action via a CLI, an agent will generally prefer that over trying to reverse‑engineer a browser UI.</li></ul><p>One of our first big steps here is a new CLI we call <strong>Tarmac</strong>. It’s an agent‑centric interface that exposes CI/CD operations, repository management, workload monitoring in our Kubernetes clusters, and log exploration and related workflows. Tarmac is built around a simple premise: if an agent can <strong>see</strong> a clean, structured way to operate the platform, it won’t need to invent its own.</p><p><strong>MCP servers and agent‑native protocols <br></strong>We’ve been aggressively rolling out Model Context Protocol (MCP) servers and a registry for our core platform capabilities so agents can:</p><ul><li>Discover what’s possible.</li><li>Call well‑defined operations.</li><li>Get structured responses instead of scraping pages.</li></ul><h4>Reducing agent friction (because it also costs money)</h4><p>Even when agents can figure things out, there’s still <strong>friction</strong>: it takes more steps, burns more tokens, increases latency, and adds complexity to prompts and orchestration. Agent friction is just another form of <strong>platform friction</strong>. We’ve always cared about human ergonomics, i.e. reducing the number of manual steps it takes to ship something. Now we’re doing the same thing for agents.</p><p>One of the most effective tools we’ve found here is <strong>markdown‑based skills and agent definitions. </strong>We encode <em>how</em> to use platform capabilities in a format agents naturally understand by pre‑packaging the “tribal knowledge” that used to live in docs, chats, or individual brains. That lets agents discover and reuse these skills instead of rediscovering how to talk to each service from scratch.</p><p>The net result: agents spend less time fumbling around and more time doing useful work. And the cost profile of that work improves.</p><h4>Internal apps as a safe testbed</h4><p>Some surfaces are too critical or too complex to hand over to agents today. A full consumer‑grade Expedia or Hotels.com experience involves hard production constraints that go far beyond what a Tailwind‑powered prototype can handle.</p><p>But <strong>internal apps</strong> are a very different story. Today, we have Backstage instances running for certain developer experiences, a variety of bespoke UIs built by different platform teams, and a lot of “pretty good” tools that, collectively, still add up to “too many interfaces.” From a builder’s perspective, this means context‑switching between a <strong>lot</strong> of different places to get anything done.</p><p>This is where agents like Claude shine. They’re very good at stitching together internal APIs, they can generate credible UIs quickly when the risk profile is lower, and ignoring which team owns which service. They only care about the underlying concepts.</p><p>We’ve started to lean into that by building a new internal experience we call <strong>Koda. Koda </strong>lives in a <strong>monorepo</strong> dedicated to agent‑built internal apps and focuses on <strong>context engineering</strong>, not on building yet another monolithic platform. It lets agents discover existing APIs, simplify authentication flows on behalf of users, and assemble a <strong>developer console organized around what developers care about</strong>, rather than around our org chart.</p><p>Our role, as humans, shifts from “build the whole thing by hand” to “define the principles and guardrails that agents use to construct and reconstruct these UIs from the ground up.”</p><h4>Where we’re heading, quickly</h4><p>Put all of this together and you get a picture of where we’re aiming over the next year.</p><p><strong>1. Keep the core capabilities battle‑tested</strong></p><p>We’re not trying to rebuild our foundations from scratch. Our core capabilities are differentiators: Deploying and running large‑scale applications, performing analytics over massive datasets, running both streaming and batch data workloads at scale, and powering high‑quality user experiences across hundreds of tenants and brands. Those components need to remain <strong>robust, reliable, and boring</strong> in the best possible way.</p><p><strong>2. Radically change the surface</strong></p><p>Where we <em>do</em> want radical change is at the <strong>surface area. We want to make</strong> <strong>APIs and auth consistent</strong> across the platform, ensure we have <strong>agent‑native channels </strong>such as CLIs like Tarmac, MCP servers, and other structured interfaces designed for automation, and package <strong>skills and agent markdown</strong> in a holistic way so builders, human or agent, can easily discover and use the platform’s capabilities. If you squint, the goal is simple: <strong>make it just as natural for an agent to operate our platform as it is for a human today</strong>.</p><p><strong>3. Embrace new failure modes</strong></p><p>As more agents interact with our systems, we’re going to discover new failure modes, edge cases, and new ways systems can be misused or overused. Instead of fearing that, we’re treating it as <strong>training data for the platform</strong>: When we see agents hacking around UIs, we respond by adding better agent interfaces. When we see complex, brittle flows, we respond by simplifying contracts and tightening guarantees. When we see friction, we respond by improving ergonomics, for both humans and agents. Over time, that feedback loop should give us <strong>more consistent interactions</strong> and <strong>more resilient infrastructure</strong>.</p><h4>Closing thoughts</h4><p>If you run or work in a platform organization today, you’re probably feeling some version of this same tension: You have a ton of battle‑tested capabilities that already work at scale and a new generation of agents that are eager to help but constrained by surfaces that weren’t built for them. You also have humans who need to reinvent their inner loop while keeping the lights on. The temptation is to treat agents as a thin layer on top of your existing tools, a smarter autocomplete or a chat window bolted onto a legacy UI.</p><p>My view is that <strong>agents are a new class of user</strong>, and we need to treat them that way with dedicated interfaces, real ergonomics, and the same care we would give a human user operating at scale.</p><p>At Expedia Group, we’re trying to meet that moment by doing double duty: reshaping how we as engineers work and reshaping the platform that our humans and our agents will share.</p><p>We’re early in that journey, but one thing is already clear: if you don’t design for agents explicitly, they’ll find their own way in anyway. Better to invite them in through the front door.</p><p><a href="https://careers.expediagroup.com/life/">Learn about life at Expedia Group</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=03e3f378a190" width="1" height="1" alt=""><hr><p><a href="https://medium.com/expedia-group-tech/reimagining-platform-engineering-for-an-agentic-future-03e3f378a190">Reimagining Platform Engineering for an Agentic Future</a> was originally published in <a href="https://medium.com/expedia-group-tech">Expedia Group Technology</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Operating Trino at Scale With Trino Gateway]]></title>
            <link>https://medium.com/expedia-group-tech/operating-trino-at-scale-with-trino-gateway-41824af788de?source=rss----38998a53046f---4</link>
            <guid isPermaLink="false">https://medium.com/p/41824af788de</guid>
            <category><![CDATA[trino-gateway]]></category>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[analytics]]></category>
            <category><![CDATA[trinos]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Prakhar Sapre]]></dc:creator>
            <pubDate>Tue, 24 Mar 2026 12:01:00 GMT</pubDate>
            <atom:updated>2026-03-24T14:32:53.194Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://medium.com/expedia-group-tech/subpage/data">Expedia Group Technology — Data</a></h4><h4>Workload‑aware routing for Trino</h4><figure><img alt="The Golden Gate Bridge at sunset" src="https://cdn-images-1.medium.com/max/1024/0*Aijgjabcwogaoqxo" /><figcaption>Photo by Joseph Barrientos on Unsplash</figcaption></figure><p>Trino — a fork of PrestoSQL — is a powerful tool in modern data analytics, enabling organizations to query large datasets quickly and efficiently. As a distributed SQL query engine, Trino provides fast, scalable insights without requiring data relocation. While Trino is robust on its own, its capabilities are further enhanced when paired with a Gateway, which introduces features such as query routing, strong security, and streamlined cluster management.</p><h3>A brief overview</h3><p>The Gateway project originated at Lyft as Presto Gateway, serving as a proxy and load balancer for PrestoDB. It was later forked and integrated into the Trino ecosystem, with contributions from various organizations and the open-source community. The Gateway serves as a central point for managing and routing queries, providing a unified interface for users and administrators.</p><p>As organizations scale their analytics platforms, they often encounter challenges such as increased query complexity, higher concurrency, and the need for specialized cluster configurations. Directing users to specific cluster endpoints becomes impractical as the user base grows. A Gateway addresses these challenges by routing queries to the most appropriate clusters based on workload, improving efficiency and responsiveness.</p><p>The Gateway acts as a vital intermediary between users and the Trino query engine. By abstracting the complexities of distributed query execution, it manages critical functions such as routing, authentication, and load balancing across diverse backend clusters. This ensures that queries are efficiently directed to the optimal processing cluster. With an intuitive user interface, the Gateway transforms what was once a convoluted process into a manageable and transparent experience empowering administrators with real-time insights and precise control over their backend cluster infrastructure. Whether it’s monitoring cluster health, usage statistics, managing query history, viewing and modifying routing rules on the fly, or managing backend clusters, the Gateway is engineered to simplify operations while enhancing system performance.</p><p>Advantages of using Trino Gateway:</p><ul><li>Use of a single connection URL for client tool users with workload distribution across multiple Trino clusters.</li><li>Automatic routing of queries to dedicated Trino clusters for specific workloads or specific queries and data sources.</li><li>No-downtime upgrades for Trino clusters behind the Gateway in a blue/green model or canary deployment model.</li><li>Transparent change of capacity of Trino clusters without user interruptions.</li></ul><h3>Example Trino Gateway architecture in Trino ecosystem</h3><figure><img alt="High-level Trino architecture: clients to Trino Gateway to Trino (with Ranger access control and monitoring via Datadog/Splunk) to Hive Metastore to Hive/S3/Iceberg storage." src="https://cdn-images-1.medium.com/max/1024/1*Sv_8s6RtcmTiPapWlB9uMw.png" /></figure><h3>Example Cluster types and workload segregation</h3><p>A common pattern for organizations using Trino at scale is to manage a fleet of clusters across different environments. These clusters can be categorized into shared and team-specific clusters, or by workload type. Typical cluster categories include:</p><ul><li>Adhoc Clusters: Often used to handle a variety of query complexities and data volumes with medium concurrency. These clusters are versatile, supporting mixed workloads that range from simple to moderately complex queries. They provide a balanced environment for exploratory data analysis and development tasks.</li><li>ETL Clusters: Optimized for high-volume, highly complex queries with low concurrency. These clusters are fine-tuned for heavy data processing tasks such as data integration, transformation, cleansing, and enrichment. The primary goal is to prepare optimized datasets for downstream consumption.</li><li>BI Clusters: Tailored for low-complexity queries with high concurrency. These clusters may be configured to refresh pre-aggregated data and support BI tools like Tableau and Looker. High concurrency ensures that multiple users can access dashboards and reports simultaneously without performance issues.</li></ul><p>This division ensures that each team or workload can optimize cluster configurations for their specific needs.</p><h3>Example Use Cases for the Gateway</h3><p>The following examples illustrate how organizations might use gateway based routing in general analytics environments.</p><ul><li>Separating Large Table Queries<br>A common challenge is that queries against massive tables can cause significant delays for smaller queries on shared clusters. By routing large table queries to specialized clusters, organizations can ensure that smaller queries execute without being queued behind resource-intensive operations. This segregation can significantly improve response times for most users.</li><li>Separating Metadata Queries<br>Metadata queries such as select version() or show catalogs are frequently run by BI tools to check cluster health. Failures in these queries can lead to subsequent extract failures. By implementing routing rules that direct metadata queries to a lightweight, single-node Trino cluster, organizations can reduce extract failure rates and improve dashboard load times. This also allows for more effective application of user-level limits on concurrency and memory, leading to fewer errors and better overall performance.</li><li>Routing BI Tool Queries<br>BI tool queries can sometimes end up on clusters not optimized for BI workloads. By using routing rules to divert these queries to dedicated BI clusters, organizations can optimize performance without requiring users to change their configurations.</li></ul><h3>Routing Rules</h3><p>Routing rules are at the heart of the Trino Gateway’s ability to direct queries to the most suitable backend clusters. These rules are written to inspect incoming queries and determine the best cluster for execution, based on factors like the tables being queried, the type of query, or the source application. Below are some practical examples that illustrate how routing rules can be used to optimize performance and reliability.</p><h4>1. Routing Large Table Queries</h4><p>When users run queries against very large tables, these operations can consume significant resources and slow down other queries on shared clusters. To prevent this, we can create a routing rule that detects when a query targets specific large tables and redirects it to a cluster optimized for heavy workloads.</p><pre>name: &quot;large-table-query&quot; <br>description: &quot;Route queries for large tables&quot; <br>actions:   <br>- |     <br>  foreach (table : trinoQueryProperties.getTables())     <br>  {       <br>    String tableSuffix = table.getSuffix();       <br>    if (tableSuffix.contains(&quot;table1&quot;) || tableSuffix.contains(&quot;table2&quot;)) <br>    {         <br>      result.put(&quot;routingGroup&quot;, &quot;large-cluster&quot;);         <br>      return;       <br>    }      <br>  } <br>condition: &quot;true&quot;</pre><h4>2. Routing Metadata Queries</h4><p>Metadata queries are lightweight queries that retrieve information about the database itself, such as select version() or show catalogs. These are often run by BI tools to check the health of the cluster before loading dashboards. If these queries fail or are delayed, it can cause subsequent data extracts to fail as well. We can create a routing rule to detect such queries and route them to a metadata cluster.</p><pre>name: &quot;metadata-queries&quot; <br>description: &quot;Routes any select version or select 1 type of queries to the metadata cluster&quot; <br>condition: &quot;true&quot; <br>actions:   <br>- |     <br>  if (trinoQueryProperties.getBody().toLowerCase().contains(&quot;select version()&quot;) || trinoQueryProperties.getBody().toLowerCase().contains(&quot;show catalogs&quot;)) <br>  {       <br>    result.put(&quot;routingGroup&quot;, &quot;metadata-cluster&quot;);       <br>    return;      <br>  }</pre><h4>3. Routing Queries from BI Tools</h4><p>Sometimes, users may inadvertently run BI tool queries (from applications like Tableau or Looker) on clusters that are not optimized for BI workloads. To address this, we can create a rule that detects the source of the query and routes it to the appropriate BI cluster.</p><pre>name: &quot;trino-gateway-bi&quot; <br>description: &quot;Route queries coming from BI tools to Gateway BI instance&quot; <br>condition: &#39;request.getHeader(&quot;X-Trino-Source&quot;) contains &quot;Tableau&quot; || request.getHeader(&quot;X-Trino-Source&quot;) contains &quot;Looker&quot;&#39; <br>actions:   - &#39;result.put(&quot;routingGroup&quot;, &quot;gateway-bi&quot;)&#39;</pre><h3>Display routing rules and modify them through the UI</h3><p>The Gateway’s routing rules are critical for directing queries to the appropriate Trino clusters. Previously, managing these rules often involved directly editing configuration files, a process prone to errors and requiring technical expertise. Also, there was no way for someone to see what rules are configured, rule inspection was required reviewing configuration files or examining the gateway environment directly. Both of these ways were not very user friendly. This made it challenging for administrators to quickly adapt routing rules to changing workloads or cluster conditions. The routing rules are the crux of the gateway since it depends on them to route the queries to the right backend cluster and it’s very important for them to be easily visible to the admins.</p><p>We have contributed a user-friendly way to display and edit routing rules directly within the Gateway’s UI. Administrators can now easily view existing rules, modify them as needed, and save the changes. These changes are persisted when a shared storage is used, ensuring that the routing rules are always up-to-date. This eliminates the need for manual configuration file editing, reducing the risk of errors and empowering administrators to easily manage routing based on their specific requirements.</p><figure><img alt="Screenshot of routing rule for Airflow queries: if X-Trino-Source header is ‘airflow’, route to ETL group." src="https://cdn-images-1.medium.com/max/1024/1*zEypADwqopoDeTvUAeKE5g.png" /><figcaption>Routing rules</figcaption></figure><p><a href="https://github.com/trinodb/trino-gateway/pull/433">Show and modify routing rules from the UI</a></p><h3>Add source filter to the history page</h3><p>Analyzing query history is essential for understanding and tracking usage patterns. However, before our contribution, filtering this history based on the <em>source</em> of the query (e.g., the application that initiated it) was a cumbersome process. This made it difficult to pinpoint queries originating from specific applications or users, hindering debugging and analysis efforts.</p><p>To address this, we implemented a source filter directly on the Gateway’s history page. This new filter allows users to easily select and filter queries based on the source client. Now, administrators and developers can quickly isolate queries from specific applications, making it much easier to diagnose issues, understand query patterns, and optimize performance. This simple addition significantly streamlines the process of analyzing query history.</p><figure><img alt="Screenshot of a routing history table showing one Looker query routed to routing group ‘adhoc’." src="https://cdn-images-1.medium.com/max/1024/1*4ML8KS8kn_9pvqA89Z-5zw.png" /><figcaption>Source filter</figcaption></figure><p><a href="https://github.com/trinodb/trino-gateway/pull/551">Add Source filter to History page</a></p><h3>Display health of the cluster</h3><p>Monitoring the health of the backend Trino clusters is paramount for ensuring optimal performance and stability. Previously, the Gateway only provided a simple active/inactive switch for each cluster, offering limited insight into the actual health status. Previously, this only allowed you to activate or deactivate cluster health checks, but did not indicate whether the cluster was ready to accept queries. This made it difficult to proactively identify potential issues or understand the overall performance of the backend clusters.</p><p>To address this, we implemented a more comprehensive cluster health display on the cluster page of the Gateway UI. Administrators can now get a quick view of the health of each backend cluster, enabling them to proactively identify potential problems, optimize resource allocation, and ensure the smooth operation of their Trino environment.</p><p>HEALTHY — A Trino cluster shows this state when health-checks report the cluster as healthy and ready. RoutingManager only routes requests to healthy clusters.</p><p>UNHEALTHY — A Trino cluster shows this state when health-checks report the cluster as unhealthy. RoutingManager does not route requests to unhealthy clusters.</p><p>PENDING — A Trino cluster shows this state when it is still starting up. It is treated as unhealthy by RoutingManager, and therefore requests are not routed to these clusters.</p><figure><img alt="Screenshot showing table able of two routing groups, ‘adhoc’ and ‘etl’, each with proxy and external URLs, zero queued/running queries, active toggles on, and red UNHEALTHY status." src="https://cdn-images-1.medium.com/max/1024/1*moQVUr4KRZ1dFjO0OMzlqw.png" /><figcaption>Cluster status</figcaption></figure><p><a href="https://github.com/trinodb/trino-gateway/pull/601">Display cluster health status on cluster page</a></p><h3>Show query text in a separate window</h3><p>Previously, the Gateway truncated query text to 200 characters for storage and display, forcing users to visit the originating cluster UI to view full queries. To make this more user friendly we added a feature to remove the 200 character limit as well as open the entire query text in a separate window. This allows users or admins to check all their queries on the Gateway side instead of going to the cluster UI always. This also improves the readability of the query.</p><figure><img alt="Screenshot of a modal window titled ‘Query Text’ showing a multi-line SQL SELECT" src="https://cdn-images-1.medium.com/max/1024/1*lcUjQl5q8s-wW6bM2utuSQ.png" /><figcaption>Query text window</figcaption></figure><p><a href="https://github.com/trinodb/trino-gateway/pull/740">Open query text in a separate window</a></p><h3>Conclusion</h3><p>The contributions above represent efforts to make the Gateway more user-friendly and powerful. By simplifying tasks like filtering query history, managing routing rules, and monitoring cluster health, these enhancements empower Trino users to focus on their data analysis tasks rather than wrestling with complex configurations. This work provided valuable learning opportunities while collaborating with the open-source community. We are excited about our contributions and will continue to add value to the project so that everyone can benefit from it. The project is available on <a href="https://github.com/trinodb/trino-gateway">https://github.com/trinodb/trino-gateway</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=41824af788de" width="1" height="1" alt=""><hr><p><a href="https://medium.com/expedia-group-tech/operating-trino-at-scale-with-trino-gateway-41824af788de">Operating Trino at Scale With Trino Gateway</a> was originally published in <a href="https://medium.com/expedia-group-tech">Expedia Group Technology</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Managing Technical Debt: Building Habits for Long-Term Agility]]></title>
            <link>https://medium.com/expedia-group-tech/managing-technical-debt-building-habits-for-long-term-agility-718aa84831e0?source=rss----38998a53046f---4</link>
            <guid isPermaLink="false">https://medium.com/p/718aa84831e0</guid>
            <category><![CDATA[product-backlog]]></category>
            <category><![CDATA[agile]]></category>
            <category><![CDATA[quality]]></category>
            <category><![CDATA[technical-debt]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Rafael Torres]]></dc:creator>
            <pubDate>Tue, 03 Mar 2026 12:01:01 GMT</pubDate>
            <atom:updated>2026-03-03T12:01:00.879Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://medium.com/expedia-group-tech/subpage/engineering">Expedia Group Technology — Engineering</a></h4><h4><strong>A lightweight framework for balancing speed today with agility tomorrow</strong></h4><figure><img alt="A view from above of downtown New York City" src="https://cdn-images-1.medium.com/max/1024/0*JWWRMix-8BFify5s" /><figcaption>Photo by Benjamín Gremler on Unsplash</figcaption></figure><p>As engineers, we’re often encouraged to “move fast” — and for good reason. Delivering value quickly is critical. But running fast usually means taking shortcuts: skipping tests, hardcoding a value, bending an abstraction a bit too far. Individually, these tradeoffs feel small. Collectively, over time, they pile up into something heavier: <strong>technical debt</strong>.</p><p>If left unpaid, technical debt will eventually slow us down more than those shortcuts ever sped us up. The question isn’t <em>if</em> we’ll incur debt, but <em>how</em> we’ll manage it.</p><h4>From “Pain-Driven Development” to today</h4><p>Years ago, I worked with a team that used the term <strong>pain-driven development </strong>well<strong> </strong>before I ever saw it mentioned elsewhere<strong>.</strong> The idea was simple: anytime you hit a painful development experience — slow builds, brittle tests, awkward APIs, manual deployment steps — write it down. Back then, we’d jot these on a whiteboard. Towards the end of each sprint, after delivering our commitments, we’d look at that board, pick the top pain points, and fix them. This practice not only surfaced technical debt early, before it became costly to address, but also revealed opportunities to improve our tools and processes in ways we might not have noticed otherwise.</p><p>This ritual created space for re-engineering and innovation:</p><ul><li>Refactoring solutions for greater maintainability and long-term flexibility.</li><li>Early automation scripts that grew into full build and deployment pipelines, long before CI/CD became standard practice.</li><li>Visualization dashboards that broadcast the status of multiple projects on team screens.</li></ul><p>The lesson: <em>pain</em> is a signal. Paying attention to it can turn frustration into progress.</p><h4>How we manage tech debt today</h4><p>On our current projects, we’ve carried forward the same spirit — but with more structure:</p><ul><li><strong>Treat tech-debt items as legitimate priorities. </strong>Using a dedicated backlog we track tech debt items in their own Epic. Whenever a pain point shows up, we log it there instead of ignoring it.</li><li><strong>Monthly backlog review.</strong> Once a month, the team revisits these items: reprioritizing, refining, and estimating them. This ensures we don’t lose sight of problems we’ve already felt.</li><li><strong>Consistent sprint allocation.</strong> Every sprint, we reserve <strong>10–15% of capacity</strong> for addressing high-priority debt items. Your percentage may vary, but the cadence matters more than the number. Habits come from routines — and addressing tech debt <em>should</em> be a habit.</li></ul><p>This practice creates a healthy rhythm: we can still move fast, but we don’t let the pile grow unchecked.</p><figure><img alt="Circular workflow diagram showing four steps to manage technical debt: Capture (log pain points), Review (monthly prioritization), Allocate (reserve sprint capacity), and Deliver (complete debt tasks). The steps form a continuous loop around the central message: “Consistent Cadence Builds Sustainable Agility.”" src="https://cdn-images-1.medium.com/max/1024/1*-ZCTjk6F0O4FxGooxas7JQ.png" /><figcaption>The Tech Debt Management Loop</figcaption></figure><h4><strong>Allocating sprint capacity</strong></h4><p>To make this concrete: in sprint planning, we don’t just look at the feature backlog. We also treat our tech-debt backlog as an equally important queue. By consistently pulling the top priority items from both with most capacity on features and a steady slice on debt, we ensure product work moves forward while we steadily reduce engineering friction.</p><figure><img alt="Diagram with two vertical queues side by side: a main backlog and a Tech Debt backlog, each showing items stacked by priority with the top item marked as highest priority. One addition vertical queue represents the sprint planning with most of the stories coming from the main backlog and ~10% from the tech-debt backlog (based in points estimations). This illustrates how sprint planning balances work by selecting from both queues." src="https://cdn-images-1.medium.com/max/1024/1*z4sKGX0jt9yVUQgTZQ7Fcg.png" /><figcaption>Sprint commitment = Top priorities from main backlog (~90%) + tech-debt backlog (~10)</figcaption></figure><h4>Whose responsibility is it?</h4><p>It’s worth calling this out explicitly: <strong>managing technical debt is engineering’s responsibility.</strong></p><p>Product, or any other stakeholders, won’t (and shouldn’t) tell us to fix flaky tests or remove a dependency we’ve outgrown. If we don’t negotiate the time and discipline to address these items, nobody else will.</p><p>Think of it like a financial loan: paying off debt requires regular installments. Skipping them might not hurt immediately, but eventually the interest compounds. Likewise, even small, steady payments on technical debt keep the codebase healthy, adaptable, and fun to work with.</p><h4>Why this matters</h4><p>Left alone, technical debt doesn’t just slow us down — it erodes morale. Developers stop enjoying the work. Velocity drops. Quality suffers.</p><p>But when a team normalizes debt repayment as part of their routine, two powerful things happen:</p><ol><li><strong>The codebase stays flexible.</strong> We can respond to change without dread.</li><li><strong>The team stays empowered.</strong> Engineers know they have agency to improve the environment they work in.</li></ol><p>That combination — adaptability and empowerment — is exactly what lets us build software that lasts.</p><h4>What you and your team can do</h4><p>If your team doesn’t already have a habit of managing tech debt, consider starting small:</p><ul><li>Create a dedicated backlog for pain points.</li><li>Review it regularly.</li><li>Allocate a slice of each sprint (no matter how small) to addressing them.</li></ul><p>The key is consistency. Over time, those small “payments” compound into a stronger, faster, happier engineering culture.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=718aa84831e0" width="1" height="1" alt=""><hr><p><a href="https://medium.com/expedia-group-tech/managing-technical-debt-building-habits-for-long-term-agility-718aa84831e0">Managing Technical Debt: Building Habits for Long-Term Agility</a> was originally published in <a href="https://medium.com/expedia-group-tech">Expedia Group Technology</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Interleaving for Accelerated Testing]]></title>
            <link>https://medium.com/expedia-group-tech/interleaving-for-accelerated-testing-75adc644027b?source=rss----38998a53046f---4</link>
            <guid isPermaLink="false">https://medium.com/p/75adc644027b</guid>
            <category><![CDATA[experimentation]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[hypothesis-testing]]></category>
            <category><![CDATA[recommender-systems]]></category>
            <category><![CDATA[a-b-testing]]></category>
            <dc:creator><![CDATA[Benjamin Stieger]]></dc:creator>
            <pubDate>Tue, 17 Feb 2026 12:01:01 GMT</pubDate>
            <atom:updated>2026-03-02T19:22:39.509Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://medium.com/expedia-group-tech/subpage/data">Expedia Group Technology — Data</a></h4><h4>Quickly identifying winning ranking models before committing to A/B tests</h4><p><em>Authors: Adam Woznica, Benjamin Stieger, and Stefania Ebli</em></p><figure><img alt="People mill about in front of the Eiffel Tower" src="https://cdn-images-1.medium.com/max/1024/0*3qEshVn1c--mcfpj" /><figcaption>Photo by Il Vagabiondo on Unsplash</figcaption></figure><p><a href="https://www.expediagroup.com/">Expedia Group</a>™ covers a portfolio of brands such as Expedia.com, Hotels.com, and Vrbo, that power lodging searches for millions of travel shoppers every day. In this competitive market <strong><em>matching users to hotel inventory is crucial</em></strong>, as users tend to quickly switch from website to website. As a result, <strong><em>having the best lodging recommendation and ranking gives the best chance of winning a sale.</em></strong></p><p>The <strong><em>lodging ranking system</em></strong> at Expedia Group consists of three main components:</p><ul><li>Selection [1]</li><li>Relevance ranking [2]</li><li>Re-ranking with business adjustments [3]</li></ul><p>These three steps are optimized to <strong><em>maximize conversion rate</em></strong> (CVR) and several <strong><em>business metrics</em></strong>. Typically, all changes in the ranking stack — whether a new ranking algorithm, a new business adjustment, new hyperparameters, or an infrastructure improvement — are <strong><em>A/B tested</em></strong> to assess the impact on the business metrics.</p><h3>The limitations of classic A/B tests</h3><p>A key limitation of A/B testing is its requirement for <strong><em>large sample sizes</em></strong> to maintain control over significance levels, test power, and the minimum relative uplift of the business metric. This becomes especially challenging when evaluating <strong><em>conversion-focused</em></strong> metrics, as these tend to be low, reflecting the relatively infrequent nature of lodging transactions.</p><p>As an example, Figure 1 visually illustrates the results of a statistical power analysis [4] for a two-sample, two-sided test for proportions. The analysis considers various base conversion rates, minimum CVR uplifts, and typical values for test power and significance levels (80% and 10%, respectively). For instance, with a base CVR of 3% and a relative uplift of 0.3%, a sample size of approximately <strong><em>92 million users</em></strong> (combined across both variants) is required. Depending on the test scope — such as restricting the sample to users eligible for personalization — this can lead to tests lasting several months. Such extended durations significantly constrain the practicality of A/B testing and limit experimental bandwidth. Moreover, running long A/B tests can introduce several technical challenges, including sample pollution (e.g., due to expired cookies, device switching, or multiple account logins), shifts in user behavior as they adapt to the experiment, and temporal effects driven by external factors such as seasonality, competitor actions, or market trends.</p><figure><img alt="Line chart showing sample size versus uplift CVR for different base CVR values (3%, 4%, 5%, and 6%). The x-axis represents uplift CVR ranging from 0.2% to 0.5%, and the y-axis represents sample size ranging from 50,000,000 to 200,000,000. Four downward-sloping curves indicate that higher uplift CVR requires smaller sample sizes. The chart notes test power = 80% and significance level = 10%." src="https://cdn-images-1.medium.com/max/1024/1*DzXUMt-uhO6Tmo2x3Ejoag.png" /><figcaption><em>Figure 1. Power analysis results for two-sided, two-sample tests of proportions.</em></figcaption></figure><h3>Interleaving: a more sensitive alternative</h3><p>In recommender systems, a well-established alternative to A/B experiments is <strong><em>interleaving testing</em></strong> [5–7]. This approach involves “blending” recommendations from different ranking variants and presenting a single <strong><em>interleaved result</em></strong> to the user, as illustrated in Figure 2. Because each user is simultaneously exposed to both variants, interleaving tests are considered <strong><em>within-subject experiments</em></strong>.</p><p>This design is a key reason why interleaving tests are significantly more sensitive than traditional A/B tests, with reported <strong><em>sensitivity increases</em></strong> ranging from <strong><em>10x to 100x</em></strong>, depending on the source [5,8].</p><figure><img alt="Diagram comparing A/B tests and interleaving tests. On the left, A/B tests show two separate users each viewing a distinct set of items: one in blue and one in red. On the right, interleaving tests show a single user viewing a combined list where blue and red items are interleaved." src="https://cdn-images-1.medium.com/max/1024/1*ty6Zv5xmXE7Hdfq-vfOOBA.png" /><figcaption><em>Figure 2. Schematic view of A/B testing vs Interleaving testing.</em></figcaption></figure><h3>Our experimentation funnel</h3><p>In recent years, interleaving testing has become a standard tool for lodging ranking systems at Expedia Group. The machine learning science team at Expedia Group leverages internal tools designed to:</p><ul><li>streamline the process of launching new interleaving tests,</li><li>running multiple tests in parallel,</li><li>monitoring variant performance, and</li><li>generating final readouts.</li></ul><p>Similar to other e-commerce companies that use interleaving as an experimentation methodology [7–8], we employ it as a <strong><em>pruning strategy</em></strong> to identify treatments for A/B testing. Among the various potential treatment variants:</p><ul><li>We use <strong><em>backtesting</em></strong> to identify those that improve the target metric (typically NDCG [9] or revenue-focused metrics).</li><li>These promising ideas are then evaluated through <strong><em>interleaving tests.</em></strong></li><li>The top-performing variants selected for <strong><em>A/B testing</em></strong>.</li></ul><p>This process is schematically represented in Figure 3.</p><figure><img alt="Flowchart illustrating the experimentation approach for ranker selection. The process starts with a cloud labeled ‘All rankers under consideration,’ followed by a box labeled ‘Rankers that improve backtesting results,’ then another box labeled ‘Rankers positive in Interleaving,’ and finally a box labeled ‘Rankers selected for A/B testing." src="https://cdn-images-1.medium.com/max/1024/1*4qBUFOUft9LFa97Oo1tVEw.png" /><figcaption><em>Figure 3. Schematical view of the experimentation approach. The size of each box does not reflect the cardinality of treatment variants.</em></figcaption></figure><h3><strong>Events, attribution and metrics</strong></h3><p>Unlike standard search engine use cases, to determine which ranking in the interleaved variants performs “better”, we assign two types of events to the elements in the interleaved lists:</p><ul><li>Property detail page views (i.e. clicks)</li><li>Booking transactions (bookings)</li></ul><p>We decided to track the above two events separately as it improves our understanding of the impact of rankings to both conversion and click-through rates. We attribute clicks and bookings to the source rankings to estimate relative preference across variants.</p><p>After attributing events to impression lists, we assign to each search a winning variant, i.e. the ranking which was assigned a higher number of clicks (or bookings); ties are also possible, e.g., when the two variants have the same number of attributed events.</p><p>To quantify the preference signal we define a <strong><em>“lift” metric</em></strong> that compares the number of searches where each variant wins, normalized to account for the number of ties. It is worth noting that the results do not strongly depend on the normalization method.</p><p>The lift metric equals 0 when A and B win an equal number of times, indicating no user preference between the two rankings. It is positive when more users prefer variant A and negative when more users prefer variant B. Note that this metric captures <em>the direction</em> of user preference in clicks (or bookings) for either ranking A or B, rather than the absolute magnitude of the uplift in conversion rate, as typically measured in an A/B test.</p><p>An equivalent lift metric can also be defined aggregated at the user level such that it compares the number of users who preferred one ranking over the alternative and ties account for the number of users without preferences. Reporting results on the user level is the default approach in our interleaving readouts.</p><h4><strong>Significance testing</strong></h4><p>A common approach in interleaving to assess whether the selected metric is significantly different from 0, beyond random chance, is to conduct significance testing using bootstrapping. More precisely, we can perform the bootstrapping percentile method to compute confidence intervals for point estimates. While this method works well as it doesn’t make any assumptions on the underlying data, it’s slow in practice even if implemented in a distributed fashion.</p><p>A faster alternative to determine confidence intervals for the observed metrics is to perform a <strong><em>t-test</em></strong> for the mean value being different than 0 of a distribution of <strong><em>winning indicators:</em></strong></p><ul><li>1 = win</li><li>-1 = loss</li><li>0 = tie</li></ul><p>This approach yields <strong><em>virtually the same results as the bootstrapping</em></strong> approach but is considerably faster. The process of attributing events, computing the metric, and performing significance testing is graphically depicted in Figure 4.</p><figure><img alt="Diagram illustrating the process of computing interleaving metrics. On the left, three user scenarios show interleaved lists of items labeled A1, A2, A3 (blue) and B1, B2, B3 (red), with clicks attributed to items. Each scenario results in an outcome: ‘Wins A,’ ‘Tie,’ or ‘Wins B.’ These outcomes feed into a lift metric calculation, shown in the center, which then leads to significance testing represented by a line chart with confidence intervals on the right." src="https://cdn-images-1.medium.com/max/1024/1*Ezj1qYzPT-NywyJaLvb8GA.png" /><figcaption><em>Figure 4. Schematic view of computing the interleaving metrics.</em></figcaption></figure><h4><strong>Sensitivity increase</strong></h4><p>Similar to other e-commerce platforms, we observed a significant increase in sensitivity when using interleaving testing. To demonstrate this, we compared the confidence intervals obtained from A/B testing and interleaving testing for two representative lodging ranking treatments that are expected to lead to deteriorated rankings:</p><ul><li><strong><em>Pinning a random property</em></strong> to a slot between positions 5 and 10.</li><li><strong><em>Randomly reshuffling</em></strong> a number of top slots.</li></ul><p>Intuitively, the impact of the first treatment is minimal, making it challenging to detect in a standard A/B test. In Figure 5, we present the confidence intervals for the lift metric as determined in an interleaving test compared to the conventional CVR uplift as measured in a traditional A/B test, as a function of sample size. We can make two main observations:</p><ul><li>Interleaving is significantly more sensitive than A/B testing and correctly detects the negative effects both of random pinning and reshuffling within a few days of data taking. A/B testing fails to detect the negative effect of random pinning even with the full sample size.</li><li>For the deteriorating treatments under test, click events are more sensitive than booking events and show a statistically significant negative result already after the first day of data taking.</li></ul><figure><img alt="Four line charts comparing lift confidence intervals for A/B tests and interleaving tests using illustrative data. The top row shows random pinning for bookings (left) and clicks (right), while the bottom row shows reshuffling for bookings (left) and clicks (right). Each chart plots sample size on the x-axis and uplift (a.u.) on the y-axis, with two colored confidence interval bands: blue for interleaving and orange for A/B testing." src="https://cdn-images-1.medium.com/max/1024/1*c11_2jruQ-skFjgl6NuUug.png" /><figcaption><em>Figure 5. Comparison of lift confidence intervals for A/B and Interleaving tests from illustrative test data on two representative ranking treatments. The lift metric used for A/B tests is the standard uplift metric on CVR. The figure layout is as follows: The two columns correspond to booking and click events, respectively. The first row shows the effect of randomly pinning a property in a position between 5 and 10; the second row shows the effect of randomly reshuffling the top slots. The x-axis indicates the sample size, while the y-axis represents the uplift metric (with negative values indicating the variant performs worse than the control). Different colors are used to distinguish between testing approaches. Note that the A/B test sample size requires twice as much time to accumulate as the population needs to be split into two buckets.</em></figcaption></figure><h3><strong>Challenges and limitations</strong></h3><p>Interleaving is a powerful tool that allows for quick exploration of new ranking models, finely segmented test readouts, and highly sensitive pre-deployment no-harm testing. However, some challenges arise, particularly related to the proper sizing of interleaving tests, interpretation of test results and assumption on the items’ independence.</p><h4>Sizing interleaving tests in business terms</h4><p>Traditional A/B tests provide measurements of the <strong><em>absolute value</em></strong> of relevant business metrics such as CVR or revenue focused metrics and allow sizing the tests in terms of a minimum detectable effect (MDE) on those same metrics. We thus know exactly how much data to collect for a desired effect size, test power, and confidence level. Interleaving, on the other hand, measures the <strong><em>relative</em></strong> user preference between two rankers, in terms of user interactions (clicks, bookings, etc.) with the search results. How those metrics relate to the business metrics is not pre-determined and can depend on the treatment being tested. Sizing interleaving tests in terms of effects on business metrics therefore requires to first establish the relationship between these metrics heuristically by carrying out a series of companion A/B and interleaving tests.</p><h4>Interpreting interleaving results</h4><p>For the same reason that sizing interleaving tests is challenging, interpreting the interleaving test results themselves <strong><em>isn’t straightforward</em></strong>. Users may well show a preference by booking items ranked higher by a new model during the interleaving test but not show a significantly different CVR or GP during the subsequent A/B test. Furthermore, interleaving is entirely blind to non-ranking differences between models, such as latency improvements.</p><h4>Independence assumption</h4><p>Another limitation of the interleaving methodology is its <strong><em>assumption that ranked items are independent</em></strong>. This becomes <strong><em>problematic for tests where effects occur at the page level</em></strong>, such as balancing impressions across different item categories (e.g., organic conventional items, sponsored listings, and vacation rentals). By breaking this assumption, interleaving can lead to inaccurate conclusions.</p><h4>Running interleaving in production</h4><p>Running interleaving tests in a dynamic production environment without interfering with either the test result or the user experience <strong><em>can be</em></strong> <strong><em>challenging</em></strong>. In practice, we either:</p><ul><li>Confine tests are confined to an <strong><em>isolated element</em></strong> of the overall ranking stack, or</li><li>Implement the interleaving framework carefully so that both variants are <strong><em>fairly represented</em></strong> in the final ranking.</li></ul><h3><strong>Conclusions</strong></h3><p><strong><em>Interleaving is a powerful alternative to A/B testing</em></strong> for evaluating ranking systems and has become an essential part of our ranking experimentation process at Expedia Group. It acts as an <strong><em>efficient method for assessing ranking quality before moving forward with A/B tests</em></strong>. In this blog post, we delved into the details of the attribution logic, metrics, and significance testing involved in interleaving. Additionally, we emphasized the importance of understanding and addressing the limitations of interleaving when applying it in practice.</p><h3><strong>References</strong></h3><p>[1] <a href="https://medium.com/expedia-group-tech/choosing-the-right-candidates-for-lodging-ranking-d0841bf40c0e">Choosing the Right Candidates for Lodging Ranking</a>, Adam Woznica and Meli Sedghi, Medium blog post</p><p>[2] <a href="https://medium.com/expedia-group-tech/learning-to-rank-at-expedia-group-how-to-adapt-the-property-search-result-page-based-on-f4ebef78c94b">Channel-Smart Property Search: How Expedia Tailors Rankings for You</a>, Anne Morvan, Medium blog post</p><p>[3] <a href="https://medium.com/expedia-group-tech/the-juggler-model-balancing-expectations-in-lodging-rankings-6d09b9b8e341">The Juggler Model: Balancing Expectations in Lodging Rankings</a>, Tiago Cunha, Medium blog post</p><p>[4] <a href="https://www.r-bloggers.com/2021/05/power-analysis-in-statistics-with-r/">Power analysis in Statistics with R</a>, blog post</p><p>[5] Large-scale validation and analysis of interleaved search evaluation, Olivier Chapelle and Thorsten Joachims and Filip Radlinski and Tisong Yue, ACM Trans. Inf. Syst., 2012</p><p>[6] Debiased balanced interleaving at Amazon Search, Nan Bi and Pablo Castells and Daniel Gilbert and Slava Galperin and Patrick Tardif and Sachin Ahuja, 2022</p><p>[7] <a href="https://netflixtechblog.com/interleaving-in-online-experiments-at-netflix-a04ee392ec55">Innovating Faster on Personalization Algorithms at Netflix Using Interleaving</a>, Joshua Parks and Juliette Aurisset and Michael Ramm, Medium blog post</p><p>[8] <a href="https://medium.com/airbnb-engineering/beyond-a-b-test-speeding-up-airbnb-search-ranking-experimentation-through-interleaving-7087afa09c8e">Beyond A/B Test : Speeding up Airbnb Search Ranking Experimentation through Interleaving</a>, Qing Zhang and Michelle Du and Reid Andersen and Liwei He, Medium blog post</p><p>[9] <a href="https://en.wikipedia.org/wiki/Discounted_cumulative_gain">https://en.wikipedia.org/wiki/Discounted_cumulative_gain</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=75adc644027b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/expedia-group-tech/interleaving-for-accelerated-testing-75adc644027b">Interleaving for Accelerated Testing</a> was originally published in <a href="https://medium.com/expedia-group-tech">Expedia Group Technology</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Quant Crossroads: UX Research or Data Science]]></title>
            <link>https://medium.com/expedia-group-tech/the-quant-crossroads-ux-research-or-data-science-e07807b19d26?source=rss----38998a53046f---4</link>
            <guid isPermaLink="false">https://medium.com/p/e07807b19d26</guid>
            <category><![CDATA[career-advice]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[analytics]]></category>
            <category><![CDATA[ux-research]]></category>
            <category><![CDATA[quantitative-ux-research]]></category>
            <dc:creator><![CDATA[Alyssa White, PhD]]></dc:creator>
            <pubDate>Tue, 27 Jan 2026 12:03:00 GMT</pubDate>
            <atom:updated>2026-02-23T09:36:48.179Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://medium.com/expedia-group-tech/data/home">Expedia Group Technology — Data</a></h4><h4>Two roles one goal — understanding users better</h4><p><em>By Sophie Rabet and Alyssa White</em></p><figure><img alt="Two people take a picture on the edge of a cliff" src="https://cdn-images-1.medium.com/max/1024/0*VHkx_19Z9GTlzxQz" /><figcaption>Photo by Samsung Memory US on Unsplash</figcaption></figure><p>Quantitative User Experience (UX) Research, as a discipline, is growing rapidly. Quant UX Con 2022, the first ever general industry conference for the discipline, was organized with the expectation of about 200 attendees. After registration exceeded 2000, the organizers were shocked to find simply how many people felt an alignment with what has historically been thought of as a niche discipline. Kerry Rodden, who gave the keynote speech at this conference, started by sharing her original job posting from 2006; the first “Quantitative UX Researcher” ever hired at Google. Fast forward to 2008 and <a href="https://hbr.org/2012/10/data-scientist-the-sexiest-job-of-the-21st-century">LinkedIn coined the term “data scientist”</a>.</p><p>While both job titles remain in their teenage years, the discipline of Data Science and the role of a data scientist has grown tremendously in the last 20 years, with no sign of stopping. In the United States, <a href="https://money.usnews.com/careers/best-jobs/data-scientist#:~:text=The%20Bureau%20of%20Labor%20Statistics,73%2C100%20jobs%20should%20open%20up.&amp;text=of%20Jobs%2073%2C100-,Data%20scientists%20use%20technology%20to%20glean%20insights,amounts%20of%20data%20they%20collect.">the Bureau of Labor Statistics</a> projects a 36% employment growth for data scientists from 2023 to 2033, which is roughly 73k jobs.</p><p>As both of these disciplines continue to grow, it helps to break down similarities and differences between them to help inform thinking around job growth and desired skill sets.</p><h4><strong>The Basics</strong></h4><p>The most underlying and foundational similarity between disciplines is connection to large datasets. Which datasets and the ways of working, however, are where the paths diverge.</p><p>QUXRs (Quantitative UX Researchers) have a very long job title for a reason: each word is an important part of the <a href="https://carljpearson.com/learn-quantitative-ux-research-self-study-resources/">skills required</a> to do the job. They are, first and foremost, researchers, which means they need to have a foundational understanding of research design skills (especially for <a href="https://drive.google.com/file/d/1NGrO77T439VuIEHMgH2dCvZnZTFkLB3Y/view?usp=sharing">survey design</a>). The research they conduct is often quantitative in nature, meaning they are working with larger samples to understand differences between groups, treatments, measures, etc. To do this type of analysis, an advanced knowledge of statistics is required, and in order to access large datasets and conduct their statistics, QUXRs must have a foundational knowledge of at least one programming language.</p><p>Meanwhile, data scientists in the tech industry use deep business knowledge to apply programming skills and machine learning techniques to analyze user behavior on sites/apps, design and analyze experiments and build datasets to monitor performance.</p><p>Within these foundational pillars, there are some shared skills. Statistical knowledge is shared between disciplines, though often with specialization emerging in terms of methodologies and with a wider knowledge of statistics in a QUXR role than in typical Data Science roles. While QUXRs will need to possess basic programming knowledge, Data Scientists will be much more advanced in this regard. Different languages are typically expected with QUXR roles focusing on statistics-oriented languages such as R, whilst Data Scientists focus more on data pulling languages such as SQL and modelling languages like Python.</p><p>Of course, within any company and team the exact expectations and roles of a QUXR and data scientist will vary. However, the crux of the difference between the two is that while both disciplines are aiming to gain insights necessary to optimize a product, data science aims to understand and predict <em>what </em>users are doing whilst QUXR aims to understand <em>why </em>they are doing it. Having these disciplines working together can provide product and design teams with a full picture of the customer journey.</p><figure><img alt="A table describing job differences between a Data Scientist and Quantitative UX Researcher" src="https://cdn-images-1.medium.com/max/1024/1*ulyTv8v7MZlYB3bgQ3PEMQ.jpeg" /><figcaption>A table describing job differences between a Data Scientist and Quantitative UX Researcher</figcaption></figure><h4><strong>Charting your path</strong></h4><p>While there are differences between our roles, that’s not to say that researchers can’t make fabulous data scientists, or vice versa. It’s all about identifying the skills that speak most to you and pursuing mastery to help inform the path you take. As stated previously, foundational knowledge of programming and statistics sit at the core of both roles, but assuming you have that squared away, how do you approach specialization?</p><p>Ask yourself: do you look at a dataset or piece of analysis and wonder if there’s a level of nuance you are missing? Do you find joy in thinking through website design choices and wondering how that might impact end user behavior and feelings? Do you find attitudinal data fascinating? Do you enjoy a well written survey question? If these questions speak to you, QUXR might be the right pathway.</p><p>Now try again: do you enjoy building models and exploring machine learning techniques? Do you enjoy making sense of large sets of data and competing signals? Do you enjoy acting like a detective to extrapolate the meaning behind data? Would you like to have a role that has the potential to jump between marketing, commercial and product? If so, data science could be right for you.</p><h4><strong>How we work differently</strong></h4><p>More often than not, QUXRs bridge the gap between data and design. They are asking UX oriented questions, like “how do these new features or new branding impact user behavior”, or “how can we measure the experience our users have with X feature”. In Google’s job description for a QUXR, they specifically call out “you’ll provide a UX perspective on quantitative data to help stakeholders understand their users”. This means that a QUXR needs to know more than just the ins and outs of the data; they need to understand the design choices and human computer-interaction principles that make the data what they are.</p><p>QUXRs collaborate more frequently with other research disciplines, like Market Research and of course Qualitative UX Research, in order to inspire or help further define their findings and data. For example, a Qual UXR may conduct a Kano study in order to identify must-have features in a new product space, and Quant UXR might pair that with a Max Diff in order to rank those features. Market Research may pull together a massive segmentation for new markets, and Quant UXR might survey existing users that meet these criteria to understand their pain points and challenges in order to inform future fixes. Researchers are curious by nature and will continue asking one another questions (ideally playing to strengths of other disciplines) until a true answer is found.</p><p>Data Scientists typically work hand-in-hand with their business counterparts in marketing and product. Their job often starts with exploring the data to uncover areas of opportunity: Where are customers dropping off? Which features are driving growth? How much value could the business unlock by improving a certain area? From there, they partner with product or marketing teams to shape hypotheses, design experiments, and test potential changes. Once the experiments run, data scientists dig into the results — translating the numbers into clear insights that help the business decide whether to double down, adjust, or pivot entirely.</p><p>On top of experimentation, data scientists also apply machine learning in practical ways. That could mean building models to forecast future performance, analyzing massive text datasets to extract meaning, or segmenting users into groups with similar behaviors. These models power things like propensity scoring (predicting how likely different users are to take an action), helping businesses make smarter, more personalized decisions at scale.</p><p>Data scientists, like researchers, are naturally inquisitive. They will keep probing the data until patterns emerge and a clear story begins to take shape. Whilst a stereotype of data scientists is often introversion, the best data scientists excel at explaining complex ideas simply to their audiences to ensure actions are taken.</p><h4><strong>How we work together</strong></h4><blockquote>One of the most valuable aspects of the collaboration between Quant UXR and Data Science at Expedia is the strong and effective partnerships established between our teams. We’ve presented at <a href="https://www.quantuxcon.org/quant-ux-con/past-conferences">conferences</a> together, built tools together, and overall elevated one another’s work by combining forces and solving problems. Let’s break this down into a few scenarios.</blockquote><p><strong><em>Problem</em></strong><em>: We want to understand at scale how new products are impacting the quality of our experiences, whether or not they’re driving immediate financial impact.</em></p><p>Solution: Quant UXR devises survey based metrics aligned to AB tests. Data Science embeds these into experiments. Both teams work together to ensure best practices are upheld from both perspectives.</p><p><strong><em>Problem</em></strong><em>: How much should we really invest in long term value of a great experience? Is it worth it?</em></p><p>Solution: Quant UXR administers a measure of experience quality. Data Science devises a causal propensity model to illustrate impact of such metrics over time. Both teams work together to illustrate tradeoffs and optimization opportunities.</p><p>In conclusion, we hope this article has been illustrative of our growing fields. We’ve included below some selected books and articles if you’re curious about Quant UXR or Data Science as a potential career path, and in either capacity we encourage you to keep learning and keep advancing your skill sets.</p><p>Books:</p><p>Quantifying the User Experience by Jeff Sauro and James Lewis</p><p>Quantitative User Experience Research by Chris Chapman and Kerry Rodden</p><p><a href="https://quantuxblog.com/">Quant UX Blog,</a> Chris Chapman</p><p><a href="https://carljpearson.com/ux-research-blog/">Figures and Frameworks</a>, Carl Pearson</p><p><a href="https://www.counting-stuff.com/">Counting Stuff</a>, Randy Au (for thoughts of a Quant UXR who has also been a Data Scientist)</p><p><a href="https://adeepgroove.substack.com/p/welcome-to-the-deep-groove?utm_campaign=post&amp;utm_medium=web">The Deep Groove</a>, Sarah Gomillion</p><p>Dataclysm: Who We Are, Christian Rudder (if you find this interesting and keep wanting to dig into the data more, Data Science might be right for you!)</p><blockquote><a href="https://careers.expediagroup.com/life/">Learn about life at Expedia Group</a></blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e07807b19d26" width="1" height="1" alt=""><hr><p><a href="https://medium.com/expedia-group-tech/the-quant-crossroads-ux-research-or-data-science-e07807b19d26">The Quant Crossroads: UX Research or Data Science</a> was originally published in <a href="https://medium.com/expedia-group-tech">Expedia Group Technology</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Powering Vector Embedding Capabilities]]></title>
            <link>https://medium.com/expedia-group-tech/powering-vector-embedding-capabilities-12e8e1480f43?source=rss----38998a53046f---4</link>
            <guid isPermaLink="false">https://medium.com/p/12e8e1480f43</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[vector-database]]></category>
            <category><![CDATA[mls]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Manisha Sudhir]]></dc:creator>
            <pubDate>Tue, 06 Jan 2026 12:02:27 GMT</pubDate>
            <atom:updated>2026-01-06T12:02:27.511Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://medium.com/expedia-group-tech/data/home">Expedia Group Technology — Data Science</a></h4><h4>Empowering developers with seamless vector embedding solutions</h4><figure><img alt="Hot air balloons over a canyon" src="https://cdn-images-1.medium.com/max/1024/0*yGEIjmeegBuRoYI_" /><figcaption>Photo by Daniela Cuevas on Unsplash</figcaption></figure><h3>Introduction</h3><p>Rapid advances in Machine Learning (ML), especially Generative AI, have increased the need for specialized capabilities like vector embedding similarity search. Vector embeddings are the numerical representations created by machine learning models which allow disparate inputs to be compared against each other. A similarity search can be accomplished by querying an indexed collection of vectors for items similar to a given vector. This process involves comparing the distance between the input vector — a single point in a multidimensional space — and each vector in the collection. Techniques such as k-nearest neighbors search (KNN or NNS) and approximate nearest neighbors search (ANN) are often employed to efficiently identify vectors that are most similar to the input vector.</p><p>Vector similarity search is gaining increased attention, particularly due to the growth in the use of large language models (LLMs). Many databases are now being created or modified to support vector similarity search capabilities. In this article we discuss how the Machine Learning Platform team at <a href="https://www.expediagroup.com/">Expedia Group</a>™ aims to reduce the engineering and integration effort required to quickly create and iterate on vector embedding use cases.</p><h3>Why do we need a centralized vector embedding service?</h3><p>In the Expedia Group <a href="https://medium.com/expedia-group-tech/unified-machine-learning-platform-at-expedia-group-5aee72606c74">ML Platform</a> team, our mission is to make it easy for our ML community to build, deploy, and iterate on ML-powered services with reliable, standardized, and reusable tools. The platform team shoulders the responsibility of creating and operating the necessary infrastructure so that each ML team can focus on applying their core skills.</p><p>With a centralized service for storing and managing embeddings, teams can easily discover, manage, and search vector data across the organization. A centralized service can link the embedding model with the vector data to avoid mixing vectors from different models or querying vectors generated by the wrong model. Additionally, it can enforce schema contracts for each vector collection to ensure compatibility is maintained for consumers when the creator of a collection makes changes.</p><p>Having a centralized service also allows us to provide composite operations for common sequences of tasks. In short, it’s all about reducing operational overhead, improving collaboration, and making life easier for everyone building with embeddings.</p><h3>What is Expedia Group’s Embedding Store Service?</h3><p>The Embedding Store Service is the comprehensive solution we developed for managing, storing and querying vector embeddings at scale. Along with leveraging <a href="https://feast.dev/">Feast</a>, an open-source feature store, it extends the functionality of traditional feature store to provide support for vector embeddings. The service provides a unified platform to manage embedding data while ensuring seamless integration with existing ML workflows. Key features include:</p><ul><li><strong>CRUD Operations</strong>: Create, read, update, and delete embeddings efficiently.</li><li><strong>Similarity Search</strong>: Ability to perform vector similarity searches across collections.</li><li><strong>Metadata Filtering</strong>: Discover existing vector embeddings by filtering based on metadata attributes such as model, version, or associated service.</li></ul><figure><img alt="Figure 1: Embedding Store Service high level architecture diagram" src="https://cdn-images-1.medium.com/max/1024/1*GEQClVbyDu5EKIv6Y-CjEQ.png" /><figcaption>Figure 1: Embedding Store Service High Level Architecture</figcaption></figure><h3>Leveraging the Feast feature store for metadata management and discoverability</h3><p>The Embedding Store Service utilizes <a href="https://feast.dev/">Feast</a> to maintain metadata about the collections created in the service. This helps maintain important information about all the collections specific to embeddings and enables discoverability.</p><p>The metadata defined can include the associated service (the system or application that generates and/or consumes the embeddings) and the specific model used to produce them. This plays a vital role in organizing and managing collections, providing benefits such as the following:</p><ol><li><strong>Data Consistency: </strong>The collection definition guarantees that all embeddings in a collection are linked to consistent metadata, such as the model and service they are associated with. This alignment prevents mismatches between embeddings and their intended applications.</li><li><strong>Search and Discoverability</strong>: Users can easily locate collections based on components of its metadata, such as a specific model or version, to discover existing vector embeddings or multiple versions of embeddings tailored to the same associated service.</li><li><strong>Version Management: </strong>Multiple versions of the same dataset, tailored to different needs and scenarios, can be created based on various factors such as different embedding models or model versions, modifying the indexing algorithms to suit various use cases or modifying the schema. This flexibility allows users to maintain a clear lineage of their data, experiment with different configurations, and seamlessly adapt to evolving requirements, all while preserving the integrity and usability of their embeddings.</li></ol><p>Feast also introduces the concepts of an “online store” and an “offline store”, which together enable efficient management of both current and historical data while supporting different types of workloads. The online store is the vector database for interactive workloads, providing performant similarity searches on the most current and relevant data. This store is optimized for real-time queries, enabling fast and efficient retrieval to support use cases like recommendation systems and semantic search.</p><p>The offline store acts as the repository for the historical dataset of a collection. It supports batch workloads such as analytical queries, experimentation, and training of new models. By maintaining a complete historical record of embeddings and their associated metadata, the offline store ensures traceability and acts as a reliable data backup.</p><p>The seamless integration between the online and offline stores allows users to restore data from the offline store to the online store whenever needed. This can be done based on various scenarios such as embeddings’ creation dates, specific time ranges, or more complex SQL queries. This flexibility ensures that data remains accessible for both real-time applications and historical analysis, providing a robust foundation for embedding workflows.</p><h3>Generating and inserting embeddings from features</h3><p>Once a collection is created, users can begin loading vector embeddings and associated data into it. There are three methods available for loading data, depending on the volume and generation process:</p><ol><li><strong>Batch Ingestion</strong>: For large volumes of embeddings generated through feature engineering processes, the Embedding Store Service provides a batch ingestion mechanism utilizing Feast materialization. This uses a Spark-based process to efficiently load data from one or more offline sources.</li><li><strong>Insert API for Small Batches or Real-Time Data</strong>: When working with smaller batches of embeddings or handling real-time embedding generation, users can use the standard Insert API to load data directly into the service.</li><li><strong>On-the-Fly Embedding Generation</strong>: For scenarios where embedding generation needs to be offloaded, the Embedding Store Service can generate embeddings dynamically by calling specific models to generate embeddings on the fly.</li></ol><p>Regardless of the method chosen to load data, the service ensures that all embeddings are stored simultaneously in both the online and offline storage systems, providing robust access for various use cases.</p><h3>Search capabilities</h3><p>Once data is stored in a collection, similarity searches can be performed to find embeddings that are most similar to a given query vector. Vector similarity search works by calculating the distance between the query vector and the vectors in the collection, leveraging the index to return the most similar results. Indexes in vector databases are designed to speed up the process by organizing and structuring the data, avoiding the need to compare the query vector against every single vector in the database — a process that would be computationally expensive. The choice of index type depends on factors such as dataset size and the balance between speed and accuracy required.</p><p>In addition to similarity search, the Embedding Store Service also supports hybrid search, which combines vector similarity search with filtering based on additional fields in the data. This enables queries that not only find similar vectors but also apply conditions, such as “price &lt; 100” or “category = electronics,” to refine the results. Hybrid search makes the queries smarter and more precise by combining the power of vector searches with traditional filtering.</p><h3>Summary and moving forward</h3><p>In this overview, we have shared the goals and capabilities of the ML Platform team’s Embedding Store Service. The advantages of the centralized service includes:</p><ul><li><strong>Reduced development time</strong> and acceleration of development and iteration of different ML experiences.</li><li><strong>Standardized APIs</strong> for ease of use and rapid development of ML applications.</li><li><strong>Discoverability and management</strong> of embeddings through seamless integration with Feast’s feature store, leveraging metadata management and collection versioning for better organization and lineage tracking.</li><li><strong>Multiple embedding workflow support</strong>, including batch ingestion, real-time insertion, and integrated embedding generation via defined models.</li><li><strong>Performant search capabilities</strong>, including similarity and hybrid searches.</li></ul><p>We aim to continue to integrate new vector database developments and provide powerful capabilities through standardized APIs. In this ever-evolving space, the Embedding Store Service will continue to power vector embedding capabilities throughout Expedia Group.</p><h3>Credits</h3><p>Written by <a href="https://medium.com/u/1a13430177b9">Manisha Sudhir</a> &amp; <a href="https://medium.com/u/875e573948c9">Timon Pike</a>. We thank our peers at <a href="https://www.expediagroup.com/">Expedia Group</a>™ for feedback, review and support.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=12e8e1480f43" width="1" height="1" alt=""><hr><p><a href="https://medium.com/expedia-group-tech/powering-vector-embedding-capabilities-12e8e1480f43">Powering Vector Embedding Capabilities</a> was originally published in <a href="https://medium.com/expedia-group-tech">Expedia Group Technology</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Functional Programming Alternative to the Strategy Pattern]]></title>
            <link>https://medium.com/expedia-group-tech/a-functional-programming-alternative-to-the-strategy-pattern-73268b68868a?source=rss----38998a53046f---4</link>
            <guid isPermaLink="false">https://medium.com/p/73268b68868a</guid>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[kotlin-beginners]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[strategy-pattern]]></category>
            <category><![CDATA[functional-programming]]></category>
            <dc:creator><![CDATA[Rafael Torres]]></dc:creator>
            <pubDate>Tue, 02 Dec 2025 06:32:20 GMT</pubDate>
            <atom:updated>2025-12-03T16:03:16.563Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://medium.com/expedia-group-tech/subpage/engineering">Expedia Group Technology — Engineering</a></h4><h4>Exploring the strategy pattern and functional programming alternatives in Kotlin</h4><figure><img alt="A person walks along sand dunes" src="https://cdn-images-1.medium.com/max/1024/0*LQEcswaxSq8xy0eP" /><figcaption>Photo by Karsten Winegeart on Unsplash</figcaption></figure><p>When designing software around business processes (e.g., orchestration services), one of the key challenges is organizing business logic in a way that is maintainable, scalable, and adaptable to change. In this post, we’ll explore how to address such challenges with the Strategy Pattern (object-oriented, OO), and a Functional Programming (FP) alternative. We’ll also discuss how to handle shared logic between strategies and compare the trade-offs of each approach.</p><blockquote>Note: The examples and patterns in this post are for educational use and do not include any proprietary information. We’ll base all the examples assuming the main logic is executed by invoking a “handler”.</blockquote><h3>The initial example: hardcoded logic in a handler</h3><p>Let’s start with a basic implementation where a Handler processes messages based on a lob (line of business) parameter. The logic is hardcoded in a when block.</p><pre>class Handler {<br>    fun handle(message: Message): Response {<br>        return when (message.lob) {<br>            &quot;LOB1&quot; -&gt; Response(&quot;Handled by Line of Business 1: ${message.content}&quot;)<br>            &quot;LOB2&quot; -&gt; Response(&quot;Handled by Line of Business 2: ${message.content}&quot;)<br>            else -&gt; Response(&quot;Unhandled line of business: ${message.lob}&quot;)<br>        }<br>    }<br>}</pre><blockquote>LOB stands for Lines of Business, but it could also represent product types, categories, or any other concept that signifies a distinct “business segment” within the solution domain.</blockquote><p>This approach works for simple scenarios, but as the number of lob values grows or the logic for each becomes more complex, the code quickly becomes unwieldy and difficult to maintain.</p><h3>Refactoring with the strategy pattern</h3><p>The Strategy Pattern (OO) offers a way to encapsulate each lob&#39;s processing logic into separate, reusable classes. The Handler delegates processing to the appropriate strategy based on the lob.</p><pre>interface MessageHandler {<br>    fun handle(message: Message): Response<br>}<br><br>class LOB1Handler : MessageHandler {<br>    override fun handle(message: Message): Response {<br>        return Response(&quot;Handled by Line of Business 1: ${message.content}&quot;)<br>    }<br>}<br><br>class LOB2Handler : MessageHandler {<br>    override fun handle(message: Message): Response {<br>        return Response(&quot;Handled by Line of Business 2: ${message.content}&quot;)<br>    }<br>}</pre><p>The Handler uses a Map to associate lob values with their respective handlers:</p><pre>class Handler {<br>    private val handlers = mapOf(<br>        &quot;LOB1&quot; to LOB1Handler(),<br>        &quot;LOB2&quot; to LOB2Handler()<br>    )<br><br>    private val defaultHandler = DefaultHandler()<br><br>    fun handle(message: Message): Response {<br>        val handler = handlers[message.lob] ?: defaultHandler<br>        return handler.handle(message)<br>    }<br>}</pre><p>This approach improves maintainability by decoupling the logic for each lob into <em>separate</em> classes. Adding a new lob simply involves creating a new MessageHandler implementation and registering it in the Handler.</p><h3>A functional programming alternative</h3><p>In the Functional Programming (FP) approach, we achieve the same separation of concerns without relying on interfaces or class hierarchies. Each handler is represented as a lambda function, and the Handler uses a Map to look up the appropriate handler.</p><pre>class Handler(private val handlers: Map&lt;String, (Message) -&gt; Response&gt;) {<br>    private val defaultHandler: (Message) -&gt; Response = { message -&gt;<br>        Response(&quot;Unhandled line of business: ${message.lob}&quot;)<br>    }<br><br>    fun handle(message: Message): Response {<br>        return handlers[message.lob]?.invoke(message) ?: defaultHandler(message)<br>    }<br>}</pre><p>Each handler is defined as a simple lambda:</p><pre>val handlers = mapOf(<br>    &quot;LOB1&quot; to { message: Message -&gt; Response(&quot;Handled by Line of Business 1: ${message.content}&quot;) },<br>    &quot;LOB2&quot; to { message: Message -&gt; Response(&quot;Handled by Line of Business 2: ${message.content}&quot;) }<br>)</pre><p>This approach is concise and avoids the need for boilerplate code, such as creating separate classes for each lob.</p><h3>Handling shared logic between handlers</h3><p>In both the OO and FP approaches, there may be shared logic that is common to all handlers. Let’s see how this is handled in each paradigm.</p><h4>OO approach with shared logic</h4><p>In the OO approach, we can move the shared logic into an abstract base class that all handlers inherit from:</p><pre>abstract class BaseMessageHandler : MessageHandler {<br>    protected fun sharedLogic(message: Message): String =<br>        &quot;Shared Prefix: ${message.content} | &quot;<br>}<br><br>class LOB1Handler : BaseMessageHandler() {<br>    override fun handle(message: Message): Response =<br>        Response(sharedLogic(message) + &quot;Handled by Line of Business 1&quot;)<br>}</pre><p>While this avoids code duplication, it introduces a deeper class hierarchy. If sub-LOBs or more complex variations arise, the hierarchy can become convoluted, making the code harder to navigate and maintain.</p><h4>FP approach with shared logic</h4><p>In the FP approach, shared logic can be passed as a parameter to each handler using higher-order functions. Defining a typealias keeps the signatures clean:</p><pre>typealias HandlerFn = (Message, (Message) -&gt; String) -&gt; Response<br><br>class Handler(private val handlers: Map&lt;String, HandlerFn&gt;) {<br>    private val defaultHandler: HandlerFn = { message, sharedLogic -&gt;<br>        Response(sharedLogic(message) + &quot;Unhandled line of business: ${message.lob}&quot;)<br>    }<br><br>    fun handle(message: Message): Response {<br>        val sharedLogic: (Message) -&gt; String = { msg -&gt; &quot;Shared Prefix: ${msg.content} | &quot; }<br>        return handlers[message.lob]?.invoke(message, sharedLogic)<br>            ?: defaultHandler(message, sharedLogic)<br>    }<br>}</pre><p>Each handler explicitly uses the shared logic:</p><pre>val handlers = mapOf(<br>    &quot;LOB1&quot; to { message: Message, sharedLogic: (Message) -&gt; String -&gt;<br>        Response(sharedLogic(message) + &quot;Handled by Line of Business 1&quot;)<br>    }<br>)</pre><p>This approach avoids hierarchy complexity and keeps the shared logic close to where it is used. Dependencies remain explicit, and the code is more composable at the cost of slightly more boilerplate in handler declarations.</p><h3>Pros and cons</h3><h4><strong>Strategy pattern approach</strong></h4><p><strong>Pros</strong></p><ul><li>Encapsulation of behavior in reusable classes.</li><li>Clear separation of concerns.</li></ul><p><strong>Cons</strong></p><ul><li>Requires more boilerplate code (e.g., interfaces, classes).</li><li>Can lead to a complex and rigid class hierarchy when handling shared logic or sub-LOBs.</li></ul><h4><strong>FP approach</strong></h4><p><strong>Pros</strong></p><ul><li>Concise and flexible implementation.</li><li>Avoids class hierarchy complexity.</li><li>Shared logic can be passed explicitly, making it easy to reuse and test.</li></ul><p><strong>Cons</strong></p><ul><li>May be less familiar to developers accustomed to OO patterns.</li><li>Shared logic must be carefully managed to avoid duplication.</li></ul><h3>Conclusion</h3><p>Both the Strategy Pattern and its Functional Programming alternative provide effective ways to structure business logic. The strategy pattern approach fits naturally with established design patterns and may feel familiar to teams with a strong strategy pattern background. The functional programming approach, by contrast, emphasizes composability and keeps shared logic explicit — helpful when you want to avoid deep class hierarchies or keep dependencies transparent.</p><p>Ultimately, the right choice depends on your project’s requirements and your team’s strengths. By weighing these trade-offs, you can pick the style that not only solves today’s problem but also scales with your codebase and team culture.</p><p><a href="https://careers.expediagroup.com/life/">Learn about life at Expedia Group</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=73268b68868a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/expedia-group-tech/a-functional-programming-alternative-to-the-strategy-pattern-73268b68868a">A Functional Programming Alternative to the Strategy Pattern</a> was originally published in <a href="https://medium.com/expedia-group-tech">Expedia Group Technology</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>