Airbnb/kotlin

2 posts

airbnb

GraphQL Data Mocking at Scale with LLMs and @generateMock (opens in new tab)

Airbnb’s `@generateMock` directive combines GraphQL schemas, product context, design references, and LLMs to generate realistic, type-safe mock data automatically. Integrated into the existing Niobe code-generation workflow, it reduces manual mock maintenance and helps client engineers prototype and test features before backend implementation is complete. ## Challenges with GraphQL Mocking - Manually creating large JSON responses or schema-generated objects is tedious and error-prone. - Client engineers often hardcode data or modify networking logic when the server is not yet ready, slowing frontend development. - Handwritten mocks drift out of sync as queries and schemas evolve. - Random generators and field-level resolvers lack the domain knowledge needed for convincing, meaningful data. ## Airbnb’s Goals - Eliminate hand-written mock data and ongoing maintenance. - Generate realistic data suitable for demos, snapshots, and tests. - Keep engineers in their normal local development workflow without requiring separate tools or repositories. ## The `@generateMock` Directive - Engineers can add `@generateMock` to GraphQL operations, fragments, or fields. - Optional arguments customize the generated data: - `id` identifies a mock and names generated helper functions. - `hints` provide instructions such as destinations, content, or desired density. - `designURL` links to a design mockup so generated names, addresses, and other values better match the intended UI. - The directive can be repeated with different arguments to create multiple mock variations. ## Integration with Niobe - After adding or changing `@generateMock` in a `.graphql` file, engineers run Niobe just as they would for ordinary GraphQL code generation. - Niobe generates: - JSON files containing the mock responses. - TypeScript, Kotlin, or Swift helpers for consuming the mocks. - Generated functions return instantiated, type-safe model objects for demo apps, snapshot tests, and unit tests. - Engineers can edit the generated JSON manually; Niobe preserves those changes during later generation runs. ## Context Used by the LLM Niobe supplies the LLM with information needed to create realistic results: - The mocked operations, fragments, fields, and their dependencies. - The relevant subset of the GraphQL schema and inline documentation. - Only schema types and fields needed to resolve the query, avoiding unnecessary context-window usage. - A snapshot image of the design referenced by `designURL`, generated through Airbnb’s internal design-document API.

airbnb

Migrating Airbnb’s JVM Monorepo to Bazel (opens in new tab)

Airbnb migrated its tens-of-millions-of-lines JVM monorepo from Gradle to Bazel over 4.5 years, achieving faster builds, testing, IntelliJ syncs, and development deployments. The move was driven by Bazel’s scalable remote execution, hermetic builds, and ability to provide shared infrastructure across Airbnb’s language-specific repositories. A gradual rollout, extensive automation, and close collaboration with service teams were central to making the migration successful. ## Results of the Migration - Build CSAT increased from 38% to 68%. - Local build and test times became 3–5 times faster. - IntelliJ syncs became 2–3 times faster. - Development-environment deployments became 2–3 times faster. ## Why Airbnb Chose Bazel ### Faster Builds Through Remote Execution - Large Gradle builds frequently took more than 20 minutes locally, while pre-merge CI builds had a p90 of 35 minutes. - Gradle had already been optimized with powerful machines and build sharding, but sharding caused underutilization and duplicated shared work. - Bazel’s cacheable actions and remote build execution enabled thousands of actions to run in parallel on short-lived workers. - “Build without the Bytes” reduced the amount of build output developers needed to download. - Bazel analysis runs in parallel, unlike the often single-threaded configuration phase of large Gradle projects. - Remote execution also improved local build performance, not just CI performance. ### More Reliable and Reproducible Builds - Gradle tasks could access the entire filesystem, creating accidental dependencies and race conditions. - Bazel sandboxes expose only declared inputs to each action, preventing undeclared files from affecting builds. - Bazel’s remote execution runs actions in identical containers with strict resource limits. - Using remote execution for both local and CI builds reduced differences between developer and CI environments. ### A Shared Build Infrastructure Layer Because Airbnb’s web, iOS, Python, Go, and JVM repositories all use Bazel, the company could standardize infrastructure for: - Remote caching - Remote build execution - Affected-target calculation - Build Event Protocol instrumentation and logging ## Starting with a Proof of Concept - Airbnb first migrated Viaduct, a large GraphQL monolith platform. - Viaduct was selected because it was complex, had slow builds, affected roughly 300 product engineers monthly, and had an infrastructure team willing to collaborate. - Bazel and Gradle initially coexisted, allowing developers to choose either system. - The team ported Viaduct’s build logic and created an automated Bazel build-file generator because the Gradle dependency graph continued to change. - Although Bazel was initially 2–4 times faster locally, developers did not adopt it immediately. - The team spent several additional months fixing missing integrations and bugs before Viaduct engineers voluntarily switched. ## Scaling Across the JVM Monorepo - Airbnb expanded breadth-first, aiming to make the entire repository compile and test under Bazel. - Gradle and Bazel continued to coexist during the migration. - This allowed developers to use Bazel locally while deployments still relied on Gradle. - Gradle provided a fallback when Bazel infrastructure, such as remote caching or execution, experienced incidents. - Maintaining two build graphs was costly, so Airbnb invested heavily in automation rather than requiring developers to maintain Bazel files manually. ## Automated Build-File Generation - The generator was inspired by Gazelle but was built internally to meet stricter performance requirements and handle dependency cycles. - It parses Java, Kotlin, and Scala source files to identify packages, imports, and symbol declarations. - These relationships are used to construct a file-level dependency graph. - Since generation ran on every commit before merging, Airbnb added external caching to keep it fast. - CI publishes a cached repository index for each mainline commit, allowing the generator to rescan only directories changed since that commit. Airbnb’s experience suggests that a large build-system migration is most effective when introduced incrementally: prove the benefits on a representative service, automate maintenance, preserve a fallback during rollout, and address developer workflow issues before expanding across the organization.