How Uber Optimizes Advertising Through Ads Simulation

🌙 Hello world ☀️ 

Martin Goetz, regarded by many as the "father of third-party software," has died at the age of 93. Goetz was notable for receiving the first software patent, awarded in 1968, for his sorting system program.

In this week’s email:

  • Architecture: How Uber optimizes advertising through ads simulation.

  • Performance: How DoorDash standardized and improved microservices caching.

  • Solid.js: The importance of locality of thinking and a pass-by-value approach.

  • Node.js: Why it’s time to transition from Buffer to Uint8Array.

  • Software Development: Critique of the software industry’s neglect of efficiency and optimization, urging a shift in development practices.

Talk is cheap. Show me the code.

Linus Torvalds

Created with Midjourney

Introduction to Ads Simulation
Uber Eats employs advertising tools to help merchants boost their sales, striving to display the most relevant ads to customers.

Traditional methods to measure changes in ad placements, ranking algorithms, and bidding strategies include costly and time-consuming experiments, or quicker but biased offline analyses.

To overcome these challenges, Uber developed the Ads Simulator, a tool that replicates various ad system scenarios, providing reliable results swiftly and affordably.

Summary of Ads Auction and Workflow

Uber Eats: Ads Auction and Bidding Flow

  1. The system initiates and gathers user context upon receiving an ad request.

  2. Potential ad campaigns matching the user's context are identified and selected.

  3. Campaigns bid in real-time, with performance optimized for pacing and budget.

  4. Winners are determined, and ad placements are assigned by the auction module.

  5. Interactions and effectiveness of the ads are tracked and analyzed.

  6. Campaigns continuously adapt their internal states based on market conditions.

Architecture and Configuration

Ads Simulator Architecture

The Ads Simulator replicates the ads auction and bidding flow, providing outcomes from potential ad strategies that reflect the real-world dynamics of the ads marketplace. It captures the complexities of budget pacing and utilizes a full spectrum of advertisers, offering a more holistic and accurate simulation.

Core Ads Flow Simulator

  • Central to the architecture, managing auctions and bids for all market advertisers.

  • Generates comprehensive simulation data logs, with inputs from Simulation Configuration and Auction Context.

Configuration

  • Enables tailoring of the simulator for a variety of ad strategies.

  • Simple adjustments of parameters allow for straightforward customization.

Auction Context

  • Consists of auctions, bidders, and user details for simulating results and adjusting future auctions.

  • Utilizes real auction logs to overcome selection bias and synthetic data for testing different market conditions.

Core Ads Flow

  • Accurately replicates entire marketplace interactions.

  • Includes Ad Campaigns with a three-agent system, Auctioneer for replicating actual auction mechanisms, and User Response Simulator for simulating customer interactions.

Logging and Analysis

  • Captures extensive simulation data, offering built-in functions for advanced analysis and visualization.

  • Highly extensible, allowing for customized integrations and valuable insights into ad strategies and marketplace dynamics.

Practical Use Cases at Uber

The Ads Simulator at Uber provides critical insights and accurately mirrors the ads marketplace dynamics, proving its reliability through real-world experimental results.

Engineers and scientists at Uber can confidently use the simulator to make well-informed decisions, enhance campaign performance, and uncover new innovative opportunities.

Use Case 1: Reserve Price Design in Auction Mechanism

  • Demonstrates the simulator's ability to efficiently find the optimal reserve price design, saving time and resources compared to traditional trial-and-error methods.

  • Experimentation results closely align with simulated results, showcasing the simulator's accuracy and its capability to significantly impact ads revenue and advertiser outcomes without risking real-world assets.

Use Case 2: Budget Allocating for Ad Campaigns

  • Assists the platform in identifying optimal geographical regions for campaign budget allocation, enhancing advertiser impact and ensuring personalized customer experiences.

  • Overcomes limitations of traditional experimentation and observational data, providing reliable data for evaluating budget scaling strategies and validating its results through online experimentation.

The presented use cases underscore the simulator's precision, efficiency, and its role as a dependable tool for driving business success at Uber.

P.S. If you’re enjoying the content of this newsletter, please share it with your network: https://www.fullstackexpress.io/subscribe

Created with Midjourney

Lev Neiman, Jason Fan

DoorDash's growing microservices architecture has led to a surge in interservice traffic, resulting in the need for a streamlined caching solution.

This issue was addressed by introducing a Kotlin library, providing a uniform, efficient, and secure method for backend developers to implement new caches, improving performance and reducing costs.

Multi-Layer Cache Request Flow

Problems and Challenges
Given DoorDash's prioritization of implementing business logic over performance optimization, there was a significant challenge in enhancing system efficiency without modifying the existing codebase.

Several issues came up as a result, including:

  • Cache Staleness: Ensuring cache remains updated with the original data source is complex, and resolving issues from outdated cache entries is time-consuming.

  • Heavy Dependency on Redis: Services often face a high rate of failure during Redis downtimes or other issues.

  • No Runtime Control: Introducing a new cache is risky without real-time adjustments; changes require new deployments or rollbacks, consuming time and resources.

  • Inconsistent Key Schema: The lack of standardized cache keys complicates debugging and tracing between Redis cache and Kotlin code.

  • Inadequate Metrics and Observability: The absence of uniform metrics across teams leads to a lack of essential data for performance analysis.

  • Difficulty in Implementing Multilayered Caching: The previous setup did not support the use of multiple caching layers for the same method easily.

Streamlined Caching and and Performance Enhancement

A simplified, streamlined approach was adopted to address these issues and ensure seamless system integration.

  • Pilot Program on DashPass: Addressed caching issues and scaling challenges by developing a simple caching library, enhancing performance with minimal disruption.

  • Standardization of Caching Clients: Introduced a simplified interface for application developers, standardizing function signatures and APIs across various caching clients for easier integration and maintenance.

  • Dependency Injection and Polymorphism: Employed to maintain consistent cache calls and ensure uniform caching processes, enhancing backend efficiency.

  • Multi-layered Caching System: Implemented a layered caching approach, comprising request local cache, local cache, and Redis cache, to optimize performance and reduce dependency on slower network layers.

  • Optimized Retrieval and Storage: Ensured quicker access to cached data in subsequent requests by storing keys in all earlier layers once found in a later layer, enhancing system efficiency.

  • Runtime Feature Flag Control: Enabled individual cache management, allowing for quick adjustments, rollouts, and tuning without new deployments, and providing flexibility in caching strategy.

  • Performance Metrics and Cache Shadowing: Collected key performance metrics and implemented a cache shadowing mechanism for validating cache entries, ensuring optimal performance and data accuracy.

  • Empirical Validation of Cache Invalidation Strategy: Utilized extensive metrics and observability into cache staleness for empirical validation, ensuring the system’s optimal functionality.

DATA STRUCTURES & ALGORITHMS
Valid Anagram

Missed the solutions to this week’s coding workout?

Learn how to use a hash table to solve this problem here.

Created with Midjourney

SolidJS, influenced by React, emphasizes design principles like unidirectional flow and explicit mutation for building user interfaces, rather than technologies like Virtual DOM. Ryan highlights the importance of "locality of thinking," enabling developers to understand and work with components in isolation, boosting productivity and maintainability. To achieve this, the article recommends a pass-by-value approach, treating all props as reactive, and avoiding implicit mutations, guiding developers to create more predictable and manageable React and SolidJS applications.

Created with Midjourney

Buffer has long been the go-to solution for handling binary data in Node.js, but it’s becoming outdated due to the cross-platform, native JavaScript type Uint8Array. The extensive methods that Buffer adds to Uint8Array lead to compatibility issues with other JavaScript environments and potential security risks. To modernize practices and avoid unpredictable behavior, it’s recommended to transition from Buffer to Uint8Array.

SOFTWARE DEVELOPMENT
Software Disenchantment

Created with Midjourney

The article expresses a deep-seated frustration with the current state of software development, highlighting the industry's disregard for efficiency and optimization in favor of faster hardware and bloated software. It draws parallels between software and other industries like automotive and construction, emphasizing how software lags behind in terms of reaching optimal performance and efficiency. The author criticizes the unnecessary complexity and size of modern applications, calling for a reevaluation of development practices to prioritize simplicity, excellence, and thoughtful resource utilization.

JAVASCRIPT ECOSYSTEM
JS Weekly Pulse

  • 📢 The React team announced that Server Actions are ready for adoption by libraries and frameworks via React Canary.

  • 🚀 Bun 1.0.7 - Optional peer dependencies in bun install, improvements to Node.js compatibility, and lots of bug fixes.

  • 🚀 Platformatic 1.0.0 - Breaking change detector for microservices and stackables.

  • 🚀 Yarn 4.0 - Hardened mode to protect against attacks, improved user interface, TypeScript integration, interactive tools, and better performance.

  • 🚀 Storybook 7.5 - Next.js improvements, enhanced Angular support, and 2.2x faster startup for React TypeScript projects.

RECOMMENDATIONS
To-Do List

 Deep Dive: Node vs Deno vs Bun.

 Register: AWS re:Invent is taking place on Nov. 27 - Dec. 1, 2023 in Las Vegas, NV. Learn about the latest cloud industry innovations, meet with AWS experts, and build connections.

 Learn: What every developer should know about GPU computing.

 Watch: Matteo Collina demonstrates how to improve Node.js API performance, increasing requests per second by 5x and reducing latency to 1/3.

 Listen: Brad Frost discusses design systems, best practices, and keeping codebases in sync on the Syntax podcast.

 Read: The Startup CTO’s Handbook, covering leadership, management and technical topics for leaders of software engineering teams

COMMUNITY SPOTLIGHT
Hot Picks in the Dev Community

OpenSheetMusicDisplay - A MusicXML renderer for the browser.

Backroad - Create web apps with no frontend-experience, all with Node.js.

Atrament - JS library for beautiful drawing and handwriting on HTML Canvas.

Nexe - command-line utility that compiles your Node.js application into a single executable file.

MEME
It Does Run 😄 

Reply

or to participate.