diff --git a/exper/raw/blog b/exper/raw/blog
new file mode 100644
index 0000000..54c19d1
--- /dev/null
+++ b/exper/raw/blog
@@ -0,0 +1,5212 @@
+Uber Engineering Bloghttps://www.uber.com/blog/engineeringThe technology behind Uber Engineering - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)RSSHubi@diygod.me (DIYgod)enWed, 08 May 2024 05:54:25 GMT1From Predictive to Generative – How Michelangelo Accelerates Uber’s AI Journey<h1 class="wp-block-heading" id="h-introduction">Introduction</h1>
+
+
+<p>In the past few years, the Machine learning (ML) adoption and impact at Uber have accelerated across all business lines. Today, ML plays a key role in Uber’s business, being used to make business-critical decisions like ETA, rider-driver matching, Eats homefeed ranking, and fraud detection. </p>
+
+
+<p>As Uber’s centralized ML platform, <a href="https://www.uber.com/blog/michelangelo-machine-learning-platform/" target="_blank" rel="noreferrer noopener">Michelangelo</a> has been instrumental in driving Uber’s ML evolution since it was first introduced in 2016. It offers a set of comprehensive features that cover the end-to-end ML lifecycle, empowering Uber’s ML practitioners to develop and productize high-quality ML applications at scale. Currently, approximately 400 active ML projects are managed on Michelangelo, with over 20K model training jobs monthly. There are more than 5K models in production, serving 10 million real-time predictions per second at peak.</p>
+
+
+<p>As shown in Figure 1 below, ML developer experience is an important multiplier that enables developers to deliver real-world business impact. By leveraging Michelangelo, Uber’s ML use cases have grown from simple tree models to advanced deep learning models, and ultimately, to the latest Generative AI. In this blog, we present the evolution of Michelangelo in the past eight years with a focus on the continuous enhancement of the ML developer experience at Uber. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/7H03P6ohPRRzlipNe07kKr3cGsFo3FYOQ1XQNZZbipKWQ5_mLrCuIaDCMtSQyrTGSJ4P-hLG7y7Z_n4C4xIA7Way05VtOWqTigGi1Haq7bBehIOMMi2d7TEW833CMJpgqqXDwBSlq2mGoq_fK8tel14" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 1: ML Developer Experience is a multiplier for delivering ML business impact.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-journey-of-ai-ml-uber">Journey of AI/ML @ Uber</h2>
+
+
+<p>Presently, Uber operates in over 10,000 cities spanning more than 70 countries, serving 25 million trips on the platform each day with 137 million monthly active users. ML has been integrated into virtually every facet of Uber’s daily operation. Virtually every interaction within the Uber apps involves ML behind the scenes. Take the rider app as an example: when users try to log in, ML is used to detect fraud signals like possible account takeovers. Within the app, in many jurisdictions, ML is deployed to suggest destination auto-completion and to rank the search results. Once the destination is chosen, ML comes into play for a multitude of functions, including ETA computation, trip price calculation, rider-driver matching with safety measures in mind, and on-trip routing. After the trip is completed, ML aids in payment fraud detection, chargeback prevention, and extends its reach to powering the customer service chatbot. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/p3awCLhFgkOjDsk_T8R0DomPhWJWm9vkP8ZTb2VqKOHi7UN1Ous3e_wqGnM-CBBkOVBnw-pmFRYtF6Ik6kl9e31_t9k-BM6BGs9532Hc3b5u6Bej89QBOlJedgeT23t7mm-iTmTq8RRFKhCpMbWFrYY" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 2: Real-time ML underpins Rider app user flow.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>As you can see in Figure 2, real-time ML powers user flow in the rider app, and the same holds true for the Eats app (and many others), as illustrated in Figure 3 below.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/Yw8-VN8tnl7p9vyZHpX0l4Su9yIzWGHlF2f3mrYbi569DAiz2us-0FLr5Ti7be5HDUFEpyZrNg7SXfBi8edCm3FpklgTkxpr1jMyhuIkuM-oNrfcZpMUjP1BYMTfy3rhCP6OL98YjobFh6GkWR3v0h0" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 3: Real-time ML underpins Eater app core user flow.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Reflecting on the evolution of ML at Uber, there are three distinct phases:</p>
+
+
+<ul><li><strong>2016 – 2019:</strong> During this initial phase, Uber primarily employed predictive machine learning for tabular data use cases. Algorithms, such as XGBoost, were used for critical tasks like ETA predictions, risk assessment, and pricing. Furthermore, Uber delved into the realm of deep learning (DL) in critical areas like 3D mapping and perception in self-driving cars, necessitating significant investments in GPU scheduling and distributed training methodologies, like Horovod®.</li>
+
+
+<li><strong>2019 – 2023:</strong> The second phase witnessed a concerted push towards the adoption of DL and collaborative model development for high-impact ML projects. The emphasis was on the model iteration as code within ML monorepo and supporting DL as a first-class citizen in Michelangelo. During this period, more than 60% of tier-1 models adopted DL in production and boosted model performance significantly.</li>
+
+
+<li><strong>Starting in 2023:</strong> The third phase represents the latest development in the new wave of Generative AI, with a focus on improving Uber’s end-user experience and internal employee productivity (described in a <a href="https://www.uber.com/blog/the-transformative-power-of-generative-ai/" target="_blank" rel="noreferrer noopener">previous blog</a>).</li>
+</ul>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/QNrwoFNrmVffQxsYS6KkqfXjHLJBBT1QHK99UO3o9KmMdC2t3DP_wUNIvUoU0dK2TOI4krdwKwb_EmV71O2Lm3vqqiYjyuzEwFq6oQZBVro17q1Xr45lpIPyEtaGpgYUEcVNXA60CxYwlJ7YJwFGJ28" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 4: Uber’s ML journey from 2016 to 2023.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Throughout this transformative journey, Michelangelo has been playing a pivotal role in advancing ML capabilities and empowering teams to build industry-leading ML applications.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-michelangelo-1-0-2016-2019">Michelangelo 1.0 (2016 – 2019)</h2>
+
+
+<p>When Uber embarked on its ML journey back in 2015, applied scientists used Jupyter Notebooks™ to develop models, while engineers built bespoke pipelines to deploy those models to production. There was no system in place to build reliable and reproducible pipelines for creating and managing training and prediction workflows at scale, and no easy way to store or compare training experiment results. More importantly, there was no established path to deploying a model into production without creating a custom serving container. </p>
+
+
+<p>In early 2016, Michelangelo was launched to standardize the ML workflows via an end-to-end system that enabled ML developers across Uber to easily build and deploy ML models at scale. It started by addressing the challenges around scalable model training and deployment to production serving containers (<a href="https://www.uber.com/blog/michelangelo-machine-learning-platform/" target="_blank" rel="noreferrer noopener">Learn more</a>). Then, a feature store named Palette was built to better manage and share feature pipelines across teams. It supported both batch and near-real-time feature computation use cases. Currently, Palette hosts more than 20,000 features that can be leveraged out-of-box for Uber teams to build robust ML models (<a href="https://www.infoq.com/presentations/michelangelo-palette-uber/" target="_blank" rel="noreferrer noopener">Learn more</a>). </p>
+
+
+<p>Other key Michelangelo components released include, but are not limited to:</p>
+
+
+<ul><li><strong>Gallery:</strong> Michelangelo’s model and ML metadata registry that provides a comprehensive search API for all types of ML entities. (<a href="https://openproceedings.org/2020/conf/edbt/paper_217.pdf" target="_blank" rel="noreferrer noopener">Learn more</a>)</li>
+
+
+<li><strong>Manifold:</strong> A model-agnostic visual debugging tool for ML at Uber. (<a href="https://www.uber.com/blog/manifold/?uclick_id=91e0edf5-abbe-49f9-b9ee-2a7c598a6a35" target="_blank" rel="noreferrer noopener">Learn more</a>) </li>
+
+
+<li><strong>PyML:</strong> A framework that speeded up the cycle of prototyping, validating, and productionizing Python ML models. (<a href="https://www.uber.com/blog/michelangelo-pyml/" target="_blank" rel="noreferrer noopener">Learn more</a>) </li>
+
+
+<li>Extend Michelangelo’s model representation for flexibility at scale. (<a href="https://www.uber.com/blog/michelangelo-machine-learning-model-representation/" target="_blank" rel="noreferrer noopener">Learn more</a>) </li>
+
+
+<li><strong>Horovod</strong> for distributed training. (<a href="https://www.uber.com/blog/horovod/" target="_blank" rel="noreferrer noopener">Learn more</a>) </li>
+</ul>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-michelangelo-2-0-2019-2023">Michelangelo 2.0 (2019 – 2023)</h2>
+
+
+<p>The initial goal of Michelangelo was to bootstrap and democratize ML at Uber. By the end of 2019, most lines of business at Uber had integrated ML into their products. Subsequently, Michelangelo’s focus started shifting from “enabling ML everywhere” to “doubling down on high-impact ML projects” so that developers could uplevel the model performance and quality of these projects to drive higher business value for Uber. Given the complexity and significance of these projects, there was a demand for more advanced ML techniques, particularly DL, and many different roles (e.g., data scientists and engineers) were often required to collaborate and iterate on models faster, as shown in Figure 5. This posed several challenges for Michelangelo 1.0, as listed below. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/2F31vZ3o80U_oyCz7LSHemUXQWNzYy6xLCkn4jIALAjnj83oO6Q8uAiCDOSo3YGDzJBCUOsgI6dKigsqOWqfmKnasgL2vQ3BQP8BOEJZkJBmpj9L4zk9sIMKaYVaHDTO6J7opoEBmGhpIz6OIGvGafU" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 5: ML lifecycle is iterative and collaborative with many different roles.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p><strong>1. Lack of comprehensive ML quality definition and project tiering</strong>: Unlike micro-services which have well-defined quality standards and best practices, at that time there was not a consistent way to measure the full spectrum of model quality. For example, many teams only measured offline model performance such as AUC and RMSE, but ignored other critical metrics like online model performance, freshness of training data, and model reproducibility. This resulted in little visibility of model performance, stale models in production, and poor dataset coverage.</p>
+
+
+<p>Also, it is important to recognize that ML projects vary significantly in terms of business impact. The lack of a distinct ML tiering system led to a uniform approach in resource allocation, support, and managing outages, regardless of a project’s impact. This resulted in high-impact projects receiving inadequate investment or not being given the priority they deserved.</p>
+
+
+<p><strong>2. Insufficient support for DL models:</strong> Up until 2019, ML use cases at Uber were predominantly using tree-based models, which inherently did not favor adopting advanced techniques like custom loss functions, incremental training, and embeddings. Conversely, Uber had vast data suitable for training DL models, but the infrastructure and developer experience challenges hindered the progress in this direction. Many teams like Maps ETA and Rider incentive teams had to invest months in developing their own DL toolkits before successfully training their first version of DL models. </p>
+
+
+<p><strong>3. Inadequacy of support for collaborative model development</strong>: In the early days, most ML projects were small-scale, and only authored and iterated by a single developer from inception to production. Hence, Michelangelo 1.0 was not optimized for highly collaborative model development, and collaboration in Michelangelo 1.0 UI and Jupyter Notebook was difficult and often done via manual copying and merging without version control or branching. In addition, there was no code review process for UI model config changes nor notebook edits, and the absence of a centralized repository for ML code and configurations led to their dispersion across various sources. These posed a significant threat to our engineering process and made large-scale model exploration across numerous ML projects arduous.</p>
+
+
+<p><strong>4. Fragmented ML tooling and developer experience: </strong>Since 2015, many ML tools other than Michelangelo have been built by different teams at Uber for a subset of the ML lifecycle and use cases, such as <a href="https://www.uber.com/blog/evolution-ds-workbench/" target="_blank" rel="noreferrer noopener">Data Science Workbench</a> (DSW) from Data team for managed Jupyter Notebooks, ML Explorer from Marketplace team for ML workflow orchestration and automation, and uFlow/uScorer from Risk team specifically for training and inferencing models from their own team. There were also different ways to develop an ML model for different model types–e.g., Michelangelo UI for SparkML and XGBoost models, Jupyter Notebook for DL models, and <a href="https://www.uber.com/blog/michelangelo-pyml/" target="_blank" rel="noreferrer noopener">PyML</a> for custom Python-based models. Launching one ML project usually required constantly switching between such semi-isolated tools, which were built with different UI patterns and user flows, leading to fragmented user experience and reduced productivity. </p>
+
+
+<p>To address these challenges, Michelangelo 2.0 re-architectured the fragmented ML platforms to a single coherent product with unified UI and API for the end-to-end ML lifecycle. Michelangelo 2.0 has four user-facing themes: (1) model quality and project tiering, (2) model iteration as code via Canvas, (3) DL as a first-class platform citizen, and (4) unified ML developer experience via MA Studio. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-architectural-overview">Architectural Overview</h3>
+
+
+<p>Michelangelo 2.0 is centered around four pillars. At the very bottom, we are enabling an architecture that allows for plug-and-play platform components. Some of the components are built in-house and others can be State-of-the-art commodity pieces from open source or 3rd party. On top is the development and production experience that caters to applied scientists and ML engineers. To improve model development velocity, we are streamlining the development experience and enabling technologies for collaborative, reusable development. We believe this approach will enable us to track and enforce compliance at the platform level. We are investing in production experiences like safe deployment of models and automatic model retraining, etc. to make it easy to maintain and manage models at scale. Finally, we are focusing on the quality of the models and investing in tooling that measures this quality across all stages and improves it systematically. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/gRuNaUCrkkMDsG1LwyLo43lqxK0Sl_dtJXQU3o2NX2VKH1wPy9SOvlPbk91_8o6dOGEsbSQz336xH1u9Z_RVi5vfoS9A2TjQg5_T5sQ7-jCrMkfRrxL4supkxIoviPLMvO8Gs0iV0QA2O0p-rxUIk_g" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 6: High-level concepts of Michelangelo 2.0 Architecture.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Here are a few architectural design principles for Michelangelo 2.0:</p>
+
+
+<ol><li>Define project tiering, and focus on high-impact use cases to maximize Uber’s ML impact. Provide self-service to long-tail ML use cases so that they can leverage the power of the platform.</li>
+
+
+<li>The majority of ML use cases can leverage Michelangelo’s core workflows and UI, while Michelangelo also enables more bespoke workflows needed for advanced use cases like deep learning.</li>
+
+
+<li>Monolithic vs. plug-and-play. Architecture will support plug-and-play of different components, but the managed solution will only support a subset of them for the best user experience. Bring your own components for advanced use cases.</li>
+
+
+<li>API/code-driven vs. UI-driven. Take the API first principle and leverage UI for visualization and fast iteration. Support model iteration as code for version control and code reviews, including changes made in UI.</li>
+
+
+<li>Build vs. buy decision. Leverage best-of-class offerings from OSS or Cloud or building in-house. OSS solutions may be prioritized over proprietary solutions. Be cautious about the cost of capacity for Cloud solutions. </li>
+
+
+<li>Codify the best ML practices like safe model deployment, model retraining, and feature monitoring in the platform. </li>
+</ol>
+
+
+<p>The system consists of three planes–i.e., control plane, offline and online data planes. The control plane defines user-facing APIs and manages the lifecycle of all entities in the system. The offline data plane does the heavy lifting on big data processing such as feature computation, model training and evaluation, offline batch inference, etc. The online data plane handles real-time model inference and feature serving, which are used by other microservices. </p>
+
+
+<p>The control plane adopts the same <a href="https://github.com/cncf/tag-app-delivery/blob/163962c4b1cd70d085107fc579e3e04c2e14d59c/operator-wg/whitepaper/Operator-WhitePaper_v1-0.md" target="_blank" rel="noreferrer noopener">Kubernetes™ Operator design pattern</a> for modularization and extensibility. The Michelangelo APIs also follow the same <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md" target="_blank" rel="noreferrer noopener">Kubernetes API conventions</a> and standardize the operations on ML-related entities like Project, Pipeline, PipelineRun, Model, Revision, InferenceServer, Deployment, etc. By leveraging the Kubernetes API machinery including API server, <a href="https://etcd.io/" target="_blank" rel="noreferrer noopener">etcd</a>, and controller manager, all Michelangelo APIs can be accessed in a consistent manner, resulting in a more user-friendly and streamlined user experience. In addition, the declarative API pattern is also crucial for Michelangelo to support mutation by both UI and code in a GIT repo, as detailed later. </p>
+
+
+<p>The offline data plane consists of a set of ML pipelines including training, scoring, evaluation, etc., which are defined as DAG of steps. The ML pipelines support intermediate checkpoints and resume between steps to avoid duplicate executions of previous steps. Steps are executed on top of frameworks like Ray™ or Spark™. The online data plane manages RPC services and streaming processing jobs that serve online prediction, online feature access, and near-real-time feature computation.<br></p>
+
+
+<p>Figure 7 shows the detailed design of the Michelangelo 2.0 system, which reduced the engineering complexity as well as simplified the external dependencies on other infrastructure components.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/MqljT9LUabDAsMHNb1k6y5LqyILCQdzWU1zi1ZD_XWneCBiYqo3Wtoda2_ysExjD0prHflRC8yBVK5Cziy2VkrQHuThszXcgvWMS4CfSZDllePznu6UB_Jw_mOZE25UA4o5gPy46woAP9uSFXrJlctI" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 7: Detailed system design of Michelangelo 2.0 including offline, online and control planes.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-model-quality-and-project-tiering">Model Quality and Project Tiering</h3>
+
+
+<p>The development and maintenance of a production-ready ML system are intricate, involving numerous stages in the model lifecycle and a complex supporting infrastructure. Typically, an ML model undergoes phases like feature engineering, training, evaluation, and serving. The lack of comprehensive ML quality measurement leads to limited visibility for ML developers regarding various quality dimensions at different stages of a model’s lifecycle. Moreover, this gap hinders organizational leaders from making fully informed decisions regarding the quality and impact of ML projects. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/bIbKLbwB7em5FhgTLHym9OHRHcaORl4UASUzEquCX0O11RkyCoOCxYbiANmykUDdFUoAZGfX7EZ_kCLyeloxxy82D_gvWZX7aYpfQmVZWPb68632BR5YjLcCSSLOznLU8Yr-Ei7QbnqSuNYiuTyu33w" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 8: Example ML quality dimensions (in yellow) in a typical ML system.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>To address these gaps, we launched Model Excellence Score (MES), a framework for measuring and monitoring key dimensions and metrics at each stage of a model’s life cycle, such as training model accuracy, prediction accuracy, model freshness, and prediction feature quality, to ensure a holistic and rigorous approach to ML deployment at scale. This framework leverages the same <a href="https://en.wikipedia.org/wiki/Service-level_agreement" target="_blank" rel="noreferrer noopener">Service Level Agreement</a> (SLA) concept that is commonly used by site reliability engineers (SREs) and DevOps professionals to manage microservices reliability in production environments. By integrating with the SLA toolset, MES establishes a standard for measuring and ensuring ML model quality at Uber. Additionally, MES tracks and visualizes the compliance and quality of models, thereby providing a clearer and more comprehensive view of ML initiatives across the organization. See <a href="https://www.uber.com/blog/enhancing-the-quality-of-machine-learning-systems-at-scale/" target="_blank" rel="noreferrer noopener">MES blog</a> for more details.</p>
+
+
+<p>To differentiate high-impact and long-tail use cases, we introduced a well-defined ML project tiering scheme. This scheme consisted of four tiers, with tier 1 being the highest. Tier 1 projects consist of models serving critical functions within core trip and core eater flows, such as ETA calculations, safety, and fraud detection, etc. Only models directly influencing core business operations can qualify for tier-1 status. Conversely, tier-4 projects typically encompass experimental and exploratory use cases with limited direct business impact. This tiering scheme enabled us to make informed decisions regarding resource allocation for ML project outage handling, resource investment, best practice enforcement, and compliance matters, among other considerations. It ensured that the level of attention and resources devoted to each project was commensurate with its relative priority and impact. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-model-iterations-as-code-nbsp">Model iterations as code </h3>
+
+
+<p>To enhance ML developer productivity, foster seamless team collaboration, and elevate the overall quality of ML applications in 2020, we launched Project Canvas. The project aimed to apply software engineering best practices for the ML development lifecycle enforcing version controls, harnessed the power of Docker containers, integrated CI/CD tools, and expedited model development by introducing standardized ML application frameworks. Key components of Canvas included:</p>
+
+
+<ul><li><strong>ML Application Framework (MAF)</strong>: Predefined, but customizable ML workflow templates to provide a code and configuration-driven way for ML development, tailor-made for intricate ML techniques such as DL.</li>
+
+
+<li><strong>ML Monorepo</strong>: A centralized repository that stores all ML development sources of truth as code, with robust version control capabilities.</li>
+
+
+<li><strong>ML Dependency Management</strong>: Provides software dependency management using Bazel and docker builds. Each ML project has their own customized docker images. In addition to software dependencies, the model training and serving code will be packaged into an immutable docker image for production model retraining and serving.</li>
+
+
+<li><strong>ML Development Environment: </strong>Provides consistent local developing and remote production execution environments for ML developers so that they can test and debug the models locally before running it in a remote production environment for fast model iteration.</li>
+
+
+<li><strong>ML Continuous Integration / Continuous Delivery</strong>: Continuous integration against the master branch and automates the deployment to production for ML models landed to the master branch of ML monorepo via various tests and validations.</li>
+
+
+<li><strong>ML Artifact Management: </strong>Provide support for artifact and lineage tracking. Artifacts are ML objects such as models, datasets and evaluation reports plus their corresponding metadata. The objects will be stored in distributed storage, and the metadata will be fully indexed and searchable.</li>
+
+
+<li><strong>MA Assistant (MAA):</strong> Michelangelo’s AutoML solution for automatic model architecture search and feature exploration/pruning.</li>
+</ul>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/Teij0cWxZToDYuyzL5LIk0iUWeSr1N3cpFnCpJGVHg8M8Hj8twroleP_flTmf6kSCkgHPXcdcTBg8-wuGN2SoaA0squnLErPVSDf2xBqPV6bz9pFlvRRXQz56LOZfWrCau7nHkfqWeTCmxCoXS5eh_A" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 9: Canvas: Streamlining end-to-end ML developer experience.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Canvas also streamlined the ML dependency management by leveraging Bazel and docker builds. Each ML project would have its custom docker images, and the model training and serving code will be packaged into an immutable docker image for production model retraining and serving. Moreover, Canvas enabled consistent local and remote development environments for ML developers to test and debug the models locally before running them in a remote production environment for fast model iteration.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-deep-learning-as-a-first-class-platform-citizen">Deep Learning as a first-class platform citizen</h3>
+
+
+<p>Adopting advanced techniques such as custom loss functions, incremental training, and embeddings posed significant challenges. DL is more flexible to address these challenges. Furthermore, DL often excels as datasets grow larger, as it can leverage more data to learn more complex representations. </p>
+
+
+<p>Before 2019, most of the DL models at Uber were for <a href="https://www.uber.com/blog/machine-learning-model-life-cycle-version-control/" target="_blank" rel="noreferrer noopener">self-driving cars</a> (e.g., <a href="https://proceedings.mlr.press/v87/yang18b/yang18b.pdf?uclick_id=91e0edf5-abbe-49f9-b9ee-2a7c598a6a35" target="_blank" rel="noreferrer noopener">3D mapping</a>, perception), computer vision (e.g., <a href="https://www.uber.com/blog/real-time-id-check/" target="_blank" rel="noreferrer noopener">driver face recognition</a>), and natural language processing (e.g., <a href="https://www.uber.com/en-AU/blog/cota/" target="_blank" rel="noreferrer noopener">customer obsession</a>) use cases. However, there were very few deep learning models for the core business, especially for tabular data use cases. One important reason that hindered the adoption of deep learning is the lack of end-to-end deep learning support in Michelangelo 1.0. Different from tree-based models, deep learning models often require much more sophisticated ML platform support, from feature transformation and model training to model serving and GPU resource management. The rest of this section will give an overview of our investment in deep learning support in Michelangelo 2.0.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h4 class="wp-block-heading" id="h-feature-transformation">Feature transformation</h4>
+
+
+<p>Michelangelo 1.0 implemented a DSL for feature transformation such as normalization and bucketization that are used in both model training and serving paths. The transformation is bundled together with a model as a <a href="https://www.uber.com/blog/michelangelo-machine-learning-model-representation/" target="_blank" rel="noreferrer noopener">Spark PipelineModel</a> so that it <a href="https://developers.google.com/machine-learning/guides/rules-of-ml#training-serving_skew" target="_blank" rel="noreferrer noopener">eliminates a source of training-serving skews.</a> However, the DSL transformation is implemented as a Spark transformer and can not be run on GPU for DL models for low-latency serving. In Michelangelo 2.0, we implemented a new DL native transformation solution that allows users to transform their features using Keras or PyTorch operators and provides advanced users the flexibility to define customized feature transformation using Python code. Similar to <a href="https://blog.research.google/2017/02/preprocessing-for-machine-learning-with.html" target="_blank" rel="noreferrer noopener">TensorFlow transform</a>, the transform graph is combined with the model inference graph either in TensorFlow or TorchScript for low-latency serving on GPUs. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h4 class="wp-block-heading" id="h-model-training">Model training</h4>
+
+
+<p>Michelangelo 2.0 supports both TensorFlow and PyTorch frameworks for large-scale DL model training by leveraging our distributed training framework Horovod. In addition, we have made the following improvements for better scalability, fault tolerance, and efficiency.</p>
+
+
+<ul><li><strong>Distributed GPU training and tuning on Ray.</strong> (<a href="https://www.youtube.com/watch?v=gMT_ONmI9RM&list=PLzTswPQNepXmLUiL4F_1VHrPcCz1OeILw&index=47" target="_blank" rel="noreferrer noopener">Learn more</a>). Historically, the model training in Michelangelo was running on top of Spark. However, DL presented new challenges on Spark such as a lack of GPU executors, mini-batch shuffle, and all-reduce. <a href="https://horovod.readthedocs.io/en/stable/spark_include.html" target="_blank" rel="noreferrer noopener">Horovod on Spark</a> wrapped the DL training using Spark estimator syntax and provided easy integration to the training pipeline. However, it also introduced many operational complexities like separate cluster jobs, lifecycle management, and failure scenarios. In Michelangelo 2.0, we have replaced Spark-based XGBoost and DL trainers with Ray-based trainers for better scalability and reliability. We also switched from an in-house hyperparameter tuning solution to RayTune. </li>
+
+
+<li><strong>Elastic Horovod with auto-scaling and fault tolerance</strong>. (<a href="https://www.uber.com/blog/horovod-ray/" target="_blank" rel="noreferrer noopener">Learn more</a>). Elastic Horovod allows distributed training that scales the number of workers dynamically throughout the training process. Jobs can now continue training with minimal interruption when machines come and go from the job.</li>
+
+
+<li><strong>Resource efficient incremental training</strong>. One advantage of DL is the ability to incrementally train a model with additional datasets without training from scratch. This significantly improves the resource efficiency for production retrains as well as increases the dataset coverage for better model accuracy. </li>
+
+
+<li><strong>Declarative DL training pipeline in Canvas</strong>. DL models require custom model code and loss functions etc. In Canvas, we designed the training pipelines to be declarative as well as extensible for users to plug-in their custom model code such as estimators, optimizers, and loss functions as shown in Figure 9.</li>
+</ul>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/wq4mV9-lSpxnYgUrC91PzO7JaMnSawey2wir-Ai0odqHzIaTkMA8erWscsRHZl22fpCQvzipR86Tkw_jgzFs3jokhk86Zqnc2OfeY882_3ChONlnLYAtEQpMCi8u6lMAw9PS8oOD-0WmtSsbEvs1bZA" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 9: Example training pipeline in Canvas for a deep learning model.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h4 class="wp-block-heading" id="h-model-serving">Model serving</h4>
+
+
+<p>Most of Uber’s tier-1 ML projects that were adopting DL are very sensitive to serving latency, such as maps ETA and Eats homefeed ranking. In addition, the model serving has to support both TensorFlow and PyTorch DL frameworks but abstract out the framework-level details away from our users. Historically, <a href="https://github.com/uber/neuropod" target="_blank" rel="noreferrer noopener">Neuropod</a> has been the default DL serving engine in Michelangelo. However, it lacks continuous community support and is being deprecated. In Michelangelo 2.0, we integrated <a href="https://github.com/triton-inference-server/server" target="_blank" rel="noreferrer noopener">Triton</a> as a next-generation model serving engine in our Online Prediction Service (OPS) as a new Spark transformer. Triton is an open-source inference server developed by Nvidia and supports multiple frameworks including TensorFlow, PyTorch, Python, and XGBoost, it is highly optimized for GPUs for low-latency serving.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h4 class="wp-block-heading" id="h-gpu-resource-management">GPU resource management</h4>
+
+
+<p>Both DL training and serving require large-scale GPU resources. Uber today manages more than five thousand GPUs across both on-premise data centers and Cloud providers like OCI and GCP. Those GPUs spread across multiple regions and many zones and clusters. The Compute clusters are in the process of migrating from <a href="https://kccna18.sched.com/event/GrTx/peloton-a-unified-scheduler-for-web-scale-workloads-on-mesos-kubernetes-min-cai-nitin-bahadur-uber" target="_blank" rel="noreferrer noopener">Peloton / Mesos</a> to <a href="https://kccncna19.sched.com/event/Uaad/kubernetizing-big-data-and-ml-workloads-at-uber-mayank-bansal-min-cai-uber" target="_blank" rel="noreferrer noopener">Kubernetes</a>. To maximize resource utilization, Uber has invested in elastic CPU and GPU resource sharing across different teams so that each team can opportunistically use the other team’s idle resources. On top of the Compute clusters, we built a job federation layer across multiple Kubernetes clusters to hide the region, and zone and cluster details for better job portability and easy Cloud migration. The job federation layer leverages the same design pattern as Kubernetes operators and is implemented as a job CRD controller in Michelangelo’s unified API framework as shown in Figure 7. Currently, the job controller supports both Spark and Ray jobs. </p>
+
+
+<p>With the end-to-end support for DL in Michelangelo 2.0, Uber has made a significant improvement in DL adoption across different business lines. In the last few years, the DL adoption in tier-1 projects has increased from almost zero to more than 60%. For example, the <a href="https://www.uber.com/blog/deepeta-how-uber-predicts-arrival-times/" target="_blank" rel="noreferrer noopener">DeepETA</a> model has more than one hundred million parameters and was trained over one billion trips. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-ma-studio-one-unified-web-ui-tool-for-everything-ml-uber">MA Studio – One unified Web UI tool for everything ML @ Uber</h3>
+
+
+<p>To address the challenges in the ML developer experience mentioned above, Michelangelo (MA) Studio was developed to unify existing Michelangelo offerings and newly built platform capabilities into one single user journey, to provide a seamless user experience, with a completely redesigned UI and UX. MA Studio provides a simplified user flow covering every step of the ML journey from feature/data prep, model training, deployment, all the way to production performance monitoring, and model CI/CD, all in one place, to improve ML developer productivity. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/23NZpcegPdWpU-kpA3971k3KKYGxjh-AMVlljf26FeKV1eAga8tCkU3vuZCgWOwlDYwDbkWXFJ0wDX-8DDsXKBGT1-ucOZbA375Pg7aectkscLfD01kJbB0EEp5vX1LSQ4ba6NhbS_N1fpX89-Dit9Y" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 10: MA Studio project landing page covering the end-to-end ML development life-cycle.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>MA Studio boasts an array of additional advantages:</p>
+
+
+<ul><li><strong>Version control and code review</strong>: All ML-related code and configurations are version controlled, and all changes go through the code review process, including models created from UI.</li>
+
+
+<li><strong>Modernized model deployment stack</strong>: Safe and incremental zonal rollout, automatic rollback triggers, and production runtime validation.</li>
+
+
+<li><strong>Built-in and unified ML observability toolkit</strong>: Model performance monitoring, feature monitoring, online/offline feature consistency check, and MES.</li>
+
+
+<li><strong>Unified ML entity lifecycle management</strong>: Users benefit from an intuitive UI and well-structured user flows for managing all ML entities, from models and pipelines to datasets and reports.</li>
+
+
+<li><strong>Enhanced debugging capabilities</strong>: MA Studio amplifies debugging capabilities and accelerates recovery for ML pipeline failures.</li>
+</ul>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/v2Dr41DHAjWT4JcMTHMRZ-EFv51edbx8RPw4BJ0MsqrnNAlI0lKoZJ-ZGRvUAZ5ez9VjNeKizUBwq-Hlxzp3uVs9i4NahPqDmgI9bOrJyBM_MC1NZjz7FD2Q46MJ_H32lP6VN3zqgEeeghht_r3mdrk" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 11: MA Studio and Canvas for standard and advanced ML use cases.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>For any ML need at Uber, you only need two tools: Canvas and MA Studio. MA Studio’s user-friendly UI covers standard ML workflows, facilitating tasks like XGB model training and the standard model retrain process without any necessity to write any code. When dealing with more sophisticated scenarios, such as DL training or customized retraining flows, Canvas is the go-to tool. Regardless of whether you’ve constructed the pipelines through Canvas or the UI, you can seamlessly execute and manage these pipelines, deploy trained models, and monitor and debug model performance—all from the MA Studio UI. Significantly, all model code and pertinent configurations are now subject to version control, and any alterations undergo a meticulous code review process, which drastically improves the quality of ML applications in production at Uber.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-generative-ai-2023-now">Generative AI (2023 – now)</h2>
+
+
+<p>Recent advancements in generative AI, particularly in the realm of large language models (LLMs), possess the capacity to radically transform our interactions with machines via natural language. Several teams at Uber are actively investigating the use of LLMs to boost internal productivity with assistants, streamline business operations with automation, and improve the end-user product with magical user experience while addressing <a href="https://en.wikipedia.org/wiki/Wikipedia:Large_language_models" target="_blank" rel="noreferrer noopener">issues associated with the use of LLMs</a>. Figure 12 shows the potential values of those three categories of generative AI use cases at Uber. <a href="https://www.uber.com/blog/the-transformative-power-of-generative-ai/" target="_blank" rel="noreferrer noopener">Learn more</a>. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/ymra4p74-37pbRET_WeL_zvyEI6I9LOg8RICp0dVRQYBEYEllRz9psRc7omJcLe6ohyJrEztIFvOK7egSKiev_hgSpI8L4CmZ_pntoRdOOaJT9DAAgWWOMonlGcLDZl0oC3OpEs21Te5R-hr7KLdG-I" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 12: Three categories of generative AI use cases at Uber.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>For developing generative AI applications, teams need access to both external LLMs through third-party APIs and/or internally hosted open-source LLMs. This is because external models have superior performance in tasks requiring general knowledge and intricate reasoning, while by leveraging the wealth of proprietary data, we can fine-tune open-source models to achieve high levels of accuracy and performance on Uber-centric tasks, at a fraction of the cost and lower latency. These fine-tuned open-source models are hosted in-house.</p>
+
+
+<p>Hence, we developed the Gen AI Gateway to provide a unified interface for teams to access both external LLMs and in-house hosted LLMs in a manner adhering to security standards and safeguarding privacy. Some of the Gen AI Gateway capabilities include:</p>
+
+
+<ul><li><strong>Logging and auditing:</strong> Ensuring comprehensive tracking and accountability.</li>
+
+
+<li><strong>Cost guardrails and attribution:</strong> Managing expenses while attributing usage, and also alerting on over usage.</li>
+
+
+<li><strong>Safety & Policy Guardrails:</strong> Ensuring LLM usage complies with our internal guidelines.</li>
+
+
+<li><strong>Personal identifiable information (PII) Redaction:</strong> Identifying and categorizing personal data, and redacting it before sending the input to external LLMs.</li>
+</ul>
+
+
+<p>To accelerate the development of generative AI applications at Uber, we have extended Michelangelo to support the full LLMOps capabilities such as fine-tuning data preparation, prompt engineering, LLM fine-tuning and evaluation, LLM deployment and serving, and production performance monitoring. Some of the key components include:</p>
+
+
+<ul><li>The Model Catalog features a collection of pre-built and ready-to-use LLMs, accessible via third-party APIs (e.g., GPT4, Google PaLM) or in-house hosted open-source LLMs on Michelangelo (e.g., Llama2). Users can explore extensive information about these LLMs within the catalog and initiate various workflows. This includes fine-tuning models in MA Studio or deploying models to online serving environments. The catalog offers a wide selection of pre-trained models, enhancing the platform’s versatility.</li>
+
+
+<li>LLM Evaluation Framework enables users to compare LLMs across different approaches (e.g., in-house vs. 3P with prompts vs 3P fine-tuned), and also evaluate improvements with iterations of prompts and models.</li>
+
+
+<li>Prompt Engineering Toolkit allows users to create and test prompts, validate the output, and save prompt templates in a centralized repository, with full version control and code review process.</li>
+</ul>
+
+
+<p>To enable cost-effective LLM fine-tuning and low-latency LLM serving, we’ve implemented several significant enhancements to Michelangelo training and serving stack:</p>
+
+
+<ul><li><strong>Integrating with Hugging Face</strong>: We implemented a Ray-based trainer for LLMs, utilizing the open source LLMs available on the <a href="https://huggingface.co/models" target="_blank" rel="noreferrer noopener">Hugging Face Hub</a> and associated libraries like <a href="https://huggingface.co/docs/peft/index" target="_blank" rel="noreferrer noopener">PEFT</a>. Fine-tuned LLMs and associated metadata are stored in Uber’s model repository, which is accessible from the model inference infrastructure.</li>
+
+
+<li><strong>Enabling Model Parallelism</strong>: Michelangelo previously did not support model parallelism for training DL models. This limitation constrained the size of trainable models to the available GPU memory, allowing, for instance, a theoretical maximum of 4 billion parameters on a 16 GB GPU. In the updated LLM training framework, we’ve integrated Deepspeed to enable model parallelism. This breakthrough eliminates the GPU memory limitation and allows for training larger DL models.</li>
+
+
+<li><strong>Elastic GPU Resource Management:</strong> We’ve provisioned Ray clusters on GPUs with the Michelangelo job controller. This provision empowers the training of LLM models on the most powerful GPUs available on-premises. Furthermore, this integration sets the stage for future extensions using cloud GPUs, enhancing scalability and flexibility.</li>
+</ul>
+
+
+<p>Leveraging these platform capabilities offered by Michelangelo, teams at Uber are fervently developing LLM-powered applications. We look forward to sharing our advancements in the productionization of LLMs soon.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-conclusion">Conclusion</h1>
+
+
+<p>ML has evolved into a fundamental driver across critical business areas at Uber. This blog delves into the eight years transformative journey of Uber’s ML platform, Michelangelo, emphasizing significant enhancements in the ML developer experience. This journey unfolded in three distinct phases: the foundational phase of predictive ML for tabular data from 2016 to 2019, a progressive shift to deep learning between 2019 and 2023, and the recent venture into generative AI starting in 2023.</p>
+
+
+<p>There have been critical lessons learned for building a large-scale, end-to-end ML platform at such a complexity level, supporting ML use cases at Uber’s scale. Key takeaways include:</p>
+
+
+<ul><li>Instituting a centralized ML platform, as opposed to having individual product teams build their own ML infrastructure, can significantly enhance ML development efficiency within a medium- or large-sized company. And the ideal ML organizational structure comprises a centralized ML platform team, complemented by dedicated data scientists and ML engineers embedded within each product team.</li>
+
+
+<li>Providing both UI-based and code/configuration-driven user flows in a unified manner is crucial for delivering a seamless ML dev experience, especially for large organizations where ML developers’ preferences of dev tools largely vary across different cohorts.</li>
+
+
+<li>The strategy of offering a high-level abstraction layer with predefined workflow templates and configurations for most users, while allowing advanced power users to directly access low-level infrastructure components to build customized pipelines and templates has proven effective.</li>
+
+
+<li>Designing the platform architecture in a modular manner so that each component can be built with a plug-and-play approach, which allows rapid adoption of state-of-the-art technologies from open source, third-party vendors, or in-house development.</li>
+
+
+<li>While Deep Learning proves powerful in solving complex ML problems, the challenge lies in supporting large-scale DL infrastructure and maintaining the performance of these models. Use DL only when its advantages align with the specific requirements. Uber’s experience has shown that in several cases, XGBoost outperforms DL in both performance and cost.</li>
+
+
+<li>Not all ML projects are created equal. Having a clear ML tiering system can effectively guide the allocation of resources and support. </li>
+</ul>
+
+
+<p>Michelangelo’s mission is to provide Uber’s ML developers with best-in-class ML capabilities and tools so that they can rapidly build, deploy, and iterate high-quality ML applications at scale. As the AI platform team, we provide in-depth ML expertise, drive standardization and innovation of ML technologies, build trust and collaborate with our partner teams, and cultivate a vibrant ML culture, so that ML is embraced and leveraged to its fullest potential. We are unwavering in our commitment to this mission, and we are incredibly enthusiastic about the promising future ahead of us.</p>
+
+
+<p>If you are interested in joining us on this exciting venture, please check our<a href="https://www.uber.com/us/en/careers/" target="_blank" rel="noreferrer noopener"> job website</a> for openings. Additionally, we look forward to collaborating with other teams in the AI/ML space to build a strong ML community and collectively accelerate the advancement of AI/ML technologies.</p>
+
+
+<p class="has-small-font-size">Apache®, Apache Spark, Spark, and the star logo are either registered trademarks or trademarks of the Apache Software Foundation in the United States and/or other countries. No endorsement by The Apache Software Foundation is implied by the use of these marks.</p>
+
+
+<p class="has-small-font-size">Horovod and Kubenetes are either registered trademarks or trademarks of the Linux Foundation® in the United States and/or other countries. No endorsement by the Linux Foundation® is implied by the use of these marks.</p>
+
+
+<p class="has-small-font-size">Ray is either a registered trademark or trademark of Anyscale, Inc in the United States and/or other countries.</p>
+https://www.uber.com/blog/from-predictive-to-generative-ai/https://www.uber.com/blog/from-predictive-to-generative-ai/Thu, 02 May 2024 09:46:07 GMTUberEngineeringAIData / MLDragonCrawl: Generative AI for High-quality Mobile Testing<h1 class="wp-block-heading" id="h-introduction"><strong>Introduction</strong></h1>
+
+
+<p>The Developer Platform team at Uber is consistently developing new and innovative ideas to enhance the developer’s experience and strengthen the quality of our apps. Quality and testing go hand in hand, and in 2023 we took on a new and exciting challenge to change how we test our mobile applications, with a focus on machine learning (ML). Specifically, we are training models to test our applications just like real humans would.</p>
+
+
+<p>Mobile testing remains an unresolved challenge, especially at our scale, encompassing thousands of developers and over 3,000 simultaneous experiments. Manual testing is usually carried out, but with high overhead, it cannot be done extensively for every minor code alteration. While test scripts can offer better scalability, they are also not immune to frequent disruptions caused by minor updates, such as new pop-ups and changes in buttons. All of these changes, no matter how minor, require recurring manual updates to the test scripts. Consequently, engineers working on this invest 30–40% of their time on maintenance. Furthermore, the substantial maintenance costs of these tests significantly hinder their adaptability and reusability across diverse cities and languages (imagine having to hire manual testers or mobile engineers for the 50+ languages that we operate in!), which makes it really difficult for us to efficiently scale testing and ensure Uber operates with high quality globally.</p>
+
+
+<p>To solve these problems, we created DragonCrawl, a system that uses large language models (LLMs) to execute mobile tests with the intuition of a human. It decides what actions to take based on the screen it sees and independently adapts to UI changes, just like a real human would.</p>
+
+
+<p>Of course, new innovations also come with new bugs, challenges, and setbacks, but it was worth it. We did not give up on our mission to bring code-free testing to the Uber apps, and towards the end of 2023, we launched DragonCrawl. Since then, we have been testing some of our most important flows with high stability, across different cities and languages, and without having to maintain them. Scaling mobile testing and ensuring quality across so many languages and cities went from humanly impossible, to possible with the help of DragonCrawl. In the three months since launching DragonCrawl, we blocked ten high-priority bugs from impacting customers while saving thousands of developer hours and reducing test maintenance costs.</p>
+
+
+<p>This blog will cover a quick introduction to large language models, deep dive into our architecture, challenges, and results. We will close by touching a little on what is in store for DragonCrawl.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-what-are-large-language-models"><strong>What Are Large Language Models?</strong></h2>
+
+
+<p>Large language models (LLMs) are a transformative development in the field of artificial intelligence, specifically within natural language processing (NLP). Essentially, LLMs are advanced models designed to understand, interpret, generate, and engage with human language in a way that is both meaningful and contextually relevant. These models are trained on vast datasets consisting of text from a wide array of sources, enabling them to learn the nuances, idioms, and syntax of natural language. One of the most critical aspects of LLMs is their ability to generate coherent and contextually relevant text based on input prompts. This capability is not limited to simple text generation; it extends to complex tasks like answering questions, translating languages, summarizing documents, and even creating content like poems or code. The underlying technology of LLMs typically involves neural network architectures, such as transformers, which are adept at handling sequential data and can capture long-range dependencies in text. This makes them particularly effective for tasks that require an understanding of context over longer stretches of text. Modern large language models are trained on many languages, which means that we can use them and get reasonable outputs in other languages.</p>
+
+
+<h3 class="wp-block-heading" id="h-why-did-we-choose-large-language-models-for-mobile-testing"><strong>Why Did We Choose Large Language Models for Mobile Testing?</strong></h3>
+
+
+<p>We realized that we could formulate mobile testing as a language generation problem. At the end of the day, mobile tests are sequences of steps, which may encounter obstacles and/or course corrections due to changes in apps, devices, etc. To successfully get through those obstacles and complete a test, we need context and goals, and the simplest way for us to provide these to an automated system is through natural language. We provide DragonCrawl with the text representation of the current screen, along with the goals of the test we want to execute, and then we ask it what we should do. Given the context, it chooses what UI element to interact with, and how to interact with it. And because these models have been pre-trained and proven resilient in languages besides English, we can ask DragonCrawl these questions with text in other languages.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="325" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-1-1024x325.png" alt="" class="wp-image-1086897" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-1.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-1.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-1.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-1.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-1.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Fig 1: High-level overview of DragonCrawl. The image of the Dragon was generated by OpenAI’s DALL·E</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-modeling"><strong>Modeling</strong></h2>
+
+
+<p>MPNet, or “Masked and Permuted Pre-training for Language Understanding,” is an advanced approach in natural language processing that combines masking and permuting strategies in pre-training language models. It works by masking some words and altering the order of others in the input text, enabling the model to learn not only the prediction of masked words, but also the broader context and syntax of the language. This dual-task approach allows MPNet to gain a deeper understanding of language semantics, surpassing traditional models that focus solely on masking or permutation. Once trained on large datasets, MPNet can be fine-tuned for a variety of NLP tasks, offering enhanced performance in understanding and generating language due to its comprehensive grasp of both word-level and sentence-level contexts.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/GXXjoxKzdTjJWERTI0nBZMaQVMb4hnarA5_B-c4XoK_GjBwkPn2VeKaM39v62RRcbik-3erep9vkXF8we1npSfj6PK3GxtTGhLRzbfFNtzYe6dpY_g1294hlsgzoLhtTPK1NpSQy2w3ca6BGYbPBpPw" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Fig 2: Transformer layers in DragonCrawl’s model.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-evaluation"><strong>Evaluation</strong></h3>
+
+
+<p>In the vast and intricate landscape of language, words are not mere strings of letters; they are rich with meaning, context, and subtle nuances and that is where embeddings come into play. Embeddings are like multi-dimensional maps, where each word finds its unique place, not just based on its own identity but also in relation to the words around it. By obtaining high-quality embeddings, we ensure that our model perceives language not as a random assortment of words, but as a coherent, interconnected fabric of ideas and meanings.</p>
+
+
+<p>We framed the evaluation as a retrieval task because we ultimately want DragonCrawl to mimic the way humans retrieve information and make decisions. Just like how we put some effort when choosing the right book in a library, DragonCrawl makes an effort to choose the right action to take to accomplish its goals. The precision@N metric, akin to finding the right book when you can only take a handful of books home, shows us the model’s ability to not just retrieve, but to pinpoint the best option in a sea of possibilities. By measuring and improving embedding quality through precision@N, we ensure that DragonCrawl does not just understand language, but comprehends it with a discerning, almost human-like acuity.</p>
+
+
+<p>To choose the right model for DragonCrawl, we tuned and evaluated several models. The table below summarizes our findings:<br></p>
+
+
+<figure class="wp-block-table"><table><tbody><tr><td></td><td>Precision@1</td><td>Precision@2</td><td>Precision@3</td><td>Parameters</td><td>Embedding size</td></tr><tr><td>MPNet (base)</td><td>0.9723</td><td>0.9623</td><td>0.9423</td><td>110M</td><td>768</td></tr><tr><td>MPNet (large)</td><td>0.9726</td><td>0.9527</td><td>0.9441</td><td>340M</td><td>768</td></tr><tr><td>T5</td><td>0.97</td><td>0.9547</td><td>0.9338</td><td>11B</td><td>3584</td></tr><tr><td>RoBERTa</td><td>0.9689</td><td>0.9512</td><td>0.9464</td><td>82M</td><td>768</td></tr><tr><td>T5 (not tuned)</td><td>0.9231</td><td>0.9213</td><td>0.9213</td><td>11B</td><td>3584</td></tr></tbody></table></figure>
+
+
+<p><br>As can be seen, embedding quality is high across all models, but latency varies significantly. The fastest model turned out to be the base MPNet, with ~110M parameters (which technically makes it a small/medium language model). Furthermore, its embedding size is 768 dimensions, which would make it less expensive for other downstream systems to use our embeddings in the future.</p>
+
+
+<p>On a different note, given those numbers, one could argue that we did not even need tuning, but that is not what we chose. T5-11b not tuned gave us good precision@1, 2, and 3, but given the frequency with which we plan to use this model, and the variability in the data because the Uber app changes constantly, we would quickly suffer from those extra points not provided by a model not customized by us.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-challenges"><strong>Challenges</strong></h2>
+
+
+<p>There were several challenges we needed to overcome during development. Some of them were specific to Uber, and some of them were related to the weaknesses of large language models.</p>
+
+
+<p>An issue we faced early on while making DragonCrawl’s request and completion of trip flows was setting up the GPS location of DragonCrawl’s (fake) riders and drivers. Uber’s matching algorithms, which are in charge of connecting riders to drivers, are very complex and are built for scale, and even take into account variables such as time of day, current traffic conditions, future demand, etc. However, when testing with DragonCrawl, there would only be 1 rider and 1 driver in a particular city at any given time, which is not what Uber’s backend expects. Thus, there were times when riders and drivers would not be matched, even if they were right next to each other. To solve this problem, we had to tune the GPS locations of both riders and drivers, so that we would get favorable results. This is very specific to Uber and/or ride-hailing and food delivery.</p>
+
+
+<h3 class="wp-block-heading" id="h-adversarial-cases"><strong>Adversarial Cases</strong></h3>
+
+
+<p>When testing Uber’s trip flow, in some cities, we saw DragonCrawl do some quirky things. In some cities, instead of requesting regular trips, it requested scheduled trips. What puzzled us the most, after debugging our artifacts carefully, is that DragonCrawl actually had all the conditions to make the right choice (i.e., touch on “Choose UberX”), but instead, it would choose a scheduled ride. Then, it would go through the UI to open a calendar and choose the date and time of the scheduled ride, which is impressive–but we digress.</p>
+
+
+<p>The example above is called an adversarial case. The concept of adversarial cases or adversarial samples was popularized a few years ago when researchers saw that it is possible to confuse a model in cases that should not be confusing at all. Let’s take a look at the image below. In the image below, we show how, if we add a little bit of noise to an image of a panda, which results in pretty much the same panda, we can confuse a machine-learning model, to the point that it would think it is a gibbon (but we all know pandas do not look like gibbons). </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter is-resized"><img decoding="async" src="https://lh7-us.googleusercontent.com/xY5iJU7vEjDJEkoUq7KFH4QIEIm9n1ZMqAhHMeBFwh35nF-jMcz2FYbRRqvoMyWoQyQDsWbMqA7-6IlIcN-LApmJMB2W_HIuXrDCV27xpLZn6BGj3XePo29RGs1jVDXEPEwxzdByEgrbNzUlcXuZiPk" alt="" style="aspect-ratio:3.6036036036036037;width:700px;height:auto" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Fig 3: Example of how imperceptible noise can fool a Machine Learning model. This is not a hypothetical example, <a href="https://www.technologyreview.com/2019/05/19/135299/how-we-might-protect-ourselves-from-malicious-ai/" target="_blank" rel="noreferrer noopener">take a look</a>.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>While it is impossible to fully rid a model of weaknesses to adversarial cases, we plan to do adversarial training and validation to reduce the risk.</p>
+
+
+<h3 class="wp-block-heading" id="h-steering-dragoncrawl-to-more-optimal-paths"><strong>Steering DragonCrawl to More Optimal Paths</strong></h3>
+
+
+<p>In our offline tests of Uber’s trip flow, we saw that DragonCrawl can always request or complete a trip, but sometimes it would take too long to do so. There were times when a new pop-up would make DragonCrawl add another passenger/book a trip for someone else, which would then load several screens with options and settings that DragonCrawl had to figure out. It would figure them out, but because there would be several steps required (rather than just 1 or 2 new steps), it would take much longer. Since our goal is to run DragonCrawl on every Android code change, we cannot afford those longer routes so we had to train Dragon to say no/skip certain things and say yes/confirm other things.</p>
+
+
+<h3 class="wp-block-heading" id="h-hallucinations"><strong>Hallucinations</strong></h3>
+
+
+<p>Finally, a topic of much discussion is hallucinations in large language models. In the words of Yann LeCun, VP and Chief AI Scientist at Meta, large language models “kind of spew nonsense sometimes” (see <a href="https://futurism.com/the-byte/yann-lecun-large-language-models-fad" target="_blank" rel="noreferrer noopener">article</a>). Indeed, we need to be mindful that we cannot fully trust large language models, or at least not without guardrails. In this section, we will discuss the guardrails we put in place to prevent hallucinations from harming DragonCrawl.</p>
+
+
+<p>First, one of DragonCrawl’s biggest strengths is the fact that it uses a smaller model. The size of our model is 110M parameters, which is roughly 3 orders of magnitude smaller than the popular GPT-3.5/4. Thus, this greatly reduces the variability and complexity of answers it can output. In other words, model size limits model non-sense.</p>
+
+
+<p>Even so, we still received some invalid outputs, and here is how we handled them:</p>
+
+
+<ol><li><strong>Partially invalid actions:</strong> It may be possible for the model to return a response where some of the information is incorrect. For instance, it may return “touch” for a UI element that is swipeable; or it may output the right action and right location, but confuse the name of the UI element (i.e. request_trip_button). For either case, since we can read from the emulator the valid actions, the correct UI element names, etc., we can resolve confusions such as the ones mentioned before. The emulator provides us with the ground truth we can use to find the right actions given the name of a UI element; the correct location given the UI element name; and even the right UI element name, given the right location.</li>
+
+
+<li><strong>Completely invalid actions:</strong> For completely invalid actions, we would append to the prompt the action previously suggested, and call out that it is invalid. This will result in a different action suggested by the model. For the case where invalid actions persist, we would backtrack and retry the suggestions from the model.</li>
+
+
+<li><strong>Loops/repeated actions:</strong> We may end up in loops (i.e., scrolling up and down in a feed) or repeated actions (i.e., repeated waits). We handle this case by keeping track of the actions already taken in the specific sequence, and even screenshots, so it is really easy to figure out if we are in a loop. Also, since DragonCrawl outputs a list of suggestions, we can just try other suggested actions.</li>
+</ol>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity is-style-default">
+
+
+<h2 class="wp-block-heading" id="h-dragoncrawl-in-action">DragonCrawl in Action</h2>
+
+
+<div class="wp-block-image"><figure class="aligncenter is-resized"><img decoding="async" src="https://lh7-us.googleusercontent.com/Jwm8lAVWCTAaQWhF_TMwOPa1NghHQJybRrqTWTrc5_HgHErdHudy8fRP4KlCzvokvruiQvBUHMsadMaO7cwumQQwvf3jCNm18TWnAtOo6jqC9r-AcoFJAwHuUiEltRSurmepasnaGAgkYeFIcbo333o" alt="" style="aspect-ratio:0.481875;width:273px;height:auto" referrerpolicy="no-referrer"></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>We have seen DragonCrawl do amazing things, but in this section, we will discuss two scenarios that really impressed us.</p>
+
+
+<h3 class="wp-block-heading" id="h-dragoncrawl-goes-online-in-australia"><strong>DragonCrawl Goes Online in Australia!</strong></h3>
+
+
+<p>In October 2023, we were testing Uber’s trip flow with DragonCrawl in Brisbane, Australia, and we saw something unexpected. DragonCrawl’s fake driver profile was perfectly set up but this time, it was not able to go online for around 5 minutes. During those 5 minutes, DragonCrawl pushed the “GO” online button repeatedly until it finally went online. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="576" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-4-1024x576.png" alt="" class="wp-image-1086898" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-4.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-4.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-4.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-4.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-4.png 2048w, https://blog.uber-cdn.com/cdn-cgi/image/width=1080,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-4.png 1080w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 4: DragonCrawl going online in Brisbane, Australia after trying for 5 minutes.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>We were pleasantly surprised. DragonCrawl is so goal-oriented that it went through an unfriendly user experience to accomplish its goals: go online, be matched to a (fake) rider, and do the hypothetical trip. Because of the time to completion, we knew we had to investigate. We also learned, as discussed more below, that DragonCrawl will not be thrown off by minor or non-reproducible bugs, like the ones that impacted our script-based QA. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-the-ultimate-solution-turn-it-off-and-then-turn-it-back-on"><strong>The ultimate solution: Turn it off, and then turn it back on</strong></h3>
+
+
+<p>It was September 2023, and we saw Dragon do something so smart, we did not know if we should laugh or clap. Dragon was testing Uber’s trip flow in Paris. It chose to go to the Paris airport (CDG), and when it got to the screen to select the payment method, the payment methods were not loading (most likely a blip in the account we were using). What did Dragon do? It closed the app, opened it, and then requested the trip again. There were no issues the second time, so Dragon accomplished its goal of going to the airport.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="576" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-5-1024x576.png" alt="" class="wp-image-1086900" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-5.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-5.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-5.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-5.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-5.png 2048w, https://blog.uber-cdn.com/cdn-cgi/image/width=1080,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-5.png 1080w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 5: DragonCrawl restarting the app to request a trip.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>It is difficult to express with words how excited and proud we are to see DragonCrawl do these things. Pushing the go online button repeatedly just to be able to drive with Uber, or opening and closing the app so that it can get to where it wants to be make DragonCrawl more resilient to minor tech issues than our old script-based testing model. </p>
+
+
+<p>We have observed that no amount of code can match the goal-oriented behavior DragonCrawl displays, and what it represents for developer productivity is exciting. It is possible to create scripts that match DragonCrawl’s strategies, but how many thousands (or even millions) lines of code would need to be written? How expensive would it be to update all of that code when needed? Now, imagine what happens when traditional tests encounter the scenarios we just described:</p>
+
+
+<ol><li><strong>Functioning driver account cannot go online for 5 minutes:</strong> This would raise eyebrows if not alerts in testing teams. We may even think there is an outage, which would alert multiple engineers, but in reality, it is a transient issue.</li>
+
+
+<li><strong>Payment method not loading:</strong> Tickets would be filed and at the highest priority. This would trigger multiple conversations, examinations, and attempts to reproduce the issue would be done, but it would only be a blip.</li>
+</ol>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-dragoncrawl-running-on-uber-s-ci"><strong>DragonCrawl Running on Uber’s CI</strong></h2>
+
+
+<p>We productionized our model and the CI pipelines where the model has been consumed since around October 2023, and got some wins by the end of the year. As of January 2024, DragonCrawl executes the core-trip flow in 5 different cities once per night, and also for the Rider and Driver Android apps before releasing them to our customers. Since we launched, we have observed the following:</p>
+
+
+<ul><li><strong>High stability:</strong> DragonCrawl executed flows with 99%+ stability in November and December 2023. The rare cases where Dragon failed were due to outages in the third-party systems we use, and also due to a real outage caused by a high-priority bug that no other mobile testing tool detected.</li>
+
+
+<li><strong>No maintenance:</strong> We did not need to manually update and/or maintain DragonCrawl. Whenever there were changes in the apps, DragonCrawl figured out how to get through those changes to accomplish its goals, unlike our team of software testers, who spent hundreds of hours maintaining test cases in 2023.</li>
+
+
+<li><strong>High reusability:</strong> We evaluated DragonCrawl in 89 of our top cities, and DragonCrawl successfully requested and completed trips in 85 of them. This is the first time at Uber that a mobile test as complex as requesting and completing a trip has been successfully executed in 85 cities worldwide without needing to tweak code.</li>
+
+
+<li><strong>Device/OS resilient:</strong> We tested Uber’s trip flow in our CI with 3 different kinds of Android devices, and 3 different OS versions, and we even varied other parameters, such as available disk, CPU, etc. DragonCrawl successfully requested and completed trips across all of these combinations without tweaks to our code or model, which is not always guaranteed in traditional mobile tests. Tuning tests to handle different screen sizes/resolutions and other device specifics is a known hassle of traditional mobile testing.</li>
+</ul>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-what-s-next"><strong>What’s Next?</strong></h2>
+
+
+<p>The foundations we set in 2023 paved the way for a very exciting 2024 and beyond. Our investments in smaller language models resulted in a foundational model with very high-quality embeddings, to the point that it unlocks the architecture shown below:</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="576" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-6-1024x576.png" alt="" class="wp-image-1086902" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-6.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-6.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-6.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-6.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-6.png 2048w, https://blog.uber-cdn.com/cdn-cgi/image/width=1080,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/juan_blog-6.png 1080w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 6: Future mobile tests as RAG applications powered by the Dragon Foundational Model (DFM)</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>With the Dragon Foundational Model (DFM), we can use small datasets (hundreds or tens of datapoints) and the DFM to create RAG (retrieval augmented generation) applications that more accurately simulate how humans interact with our applications. Those smaller datasets (with verbal goals and preferences), would tell DragonCrawl what to optimize for, and that is all it needs. The DFM may be a LLM, but it is secretly a rewards model that takes actions to accomplish its goals, and as we have seen, some of those actions mimic what a real human would do.</p>
+
+
+<p>In 2024, a big area of investment for us will be to build the subsystems that will empower developers to build their tests as RAGs, and reap the benefits of flawlessly executing in many cities, languages, and with minimal (or even zero) maintenance costs.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-conclusion">Conclusion</h1>
+
+
+<p>With all the advancements generative AI has seen over the past 4-6 months, there are more things to evaluate to improve our model and the quality of our apps. We plan to evaluate more modern large language models to push the quality of our models even further. Every increase in model quality will increase the combinations we can test, bringing down bugs that reach our users, which in turn increases productivity, enabling developers to build new experiences, and giving DragonCrawl more things to test. This is a flywheel that gets kicked off and accelerates with model quality, and we will fuel this acceleration.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/DFEnnSB2E5rc241fUWUqJVypOJkESM0sMISfkqL-Qtq3B4gP212JD-Lw9AqaP0pRkzpo_RO25TyEBxG6NuJmqy4aRCq9XQ93l7zbEBZKfUUJriwCZAo-00dz56fReF7GrGD1eijSgGiFrx8j6ARmN0o" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 7: Model-quality fly wheel.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-acknowledgments"><strong>Acknowledgments</strong></h3>
+
+
+<p>Something as complex as DragonCrawl without the help of our partner teams. We are very thankful to Uber’s CI, Mobile Foundations, Michelangelo, Mobile Release and Test accounts. We would also like to thank you the passionate researchers that created <a href="https://arxiv.org/abs/2004.09297" target="_blank" rel="noreferrer noopener">MPNet</a> (which we use), T5, and other LLMs for their contributions to the field and for enabling others to advance their own fields. Finally, we want to send a big thank you to our former intern <a href="https://www.linkedin.com/in/gustavonazarioperez/" target="_blank" rel="noreferrer noopener">Gustavo Nazario</a>, who helped us turn DragonCrawl into what it is today.</p>
+
+
+<p class="has-small-font-size">Cover photo attribution: This image was generated using OpenAI’s DALL·E.</p>
+https://www.uber.com/blog/generative-ai-for-high-quality-mobile-testing/https://www.uber.com/blog/generative-ai-for-high-quality-mobile-testing/Tue, 23 Apr 2024 05:00:00 GMTUberAIEnsuring Precision and Integrity: A Deep Dive into Uber’s Accounting Data Testing Strategies<h1 class="wp-block-heading" id="h-introduction">Introduction</h1>
+
+
+<p>Uber operates multiple lines of business across diverse global regions. Financial Accounting Services (FAS) Platform (<a href="https://www.uber.com/en-IN/blog/ubers-finance-computation-platform/" target="_blank" rel="noreferrer noopener">detailed architecture</a>) is responsible for financial accounting across these global regions and is designed to follow the tenets below:</p>
+
+
+<ul><li>Compliance</li>
+
+
+<li>Auditability</li>
+
+
+<li>Accuracy</li>
+
+
+<li>Scalability</li>
+
+
+<li>Analytics</li>
+</ul>
+
+
+<p>To maintain these tenets, FAS has built robust testing, monitoring, and alerting processes. This encompasses system configuration, business accounting, and external financial report generation.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-challenges">Challenges</h2>
+
+
+<p>The financial accounting services platform at Uber operates at an internet scale– approximately 1.5 billion journal entries (JEs) per day and 120 million transactions per day via ETL and data processing at a throughput of 2,500 queries per second [on average]. Standard off-the-shelf accounting systems cannot support such scale and scope of transactions of our growing platform. Additionally, we manage data from over 25 different services for accounting purposes. To handle data at this scale, our engineering systems are designed to process data both at the event level and in a batch mode. As data flows through multiple components in the architecture, there is a need to ensure that all the components are designed to embrace the tenets defined above. </p>
+
+
+<p>The platform processed roughly $120+ billion in annual gross bookings and settlements in 2023. It operates at a transaction scale (~80 billion financial microtransactions per year) that is 10 times the trip scale and currently offers 99.6% of transactions with automated revenue computation with 99.99% completeness, accuracy guarantee, and auditability. We onboarded 600+ business changes to support the scaling of the business in 2023. The platform processes big data and stores petabytes of data in Schemaless and Apache Hive<sup>TM</sup>.</p>
+
+
+<p>The accounting process has multiple steps and validations are required at every step to adhere to the tenets. Here are the various steps where validations are performed:</p>
+
+
+<ol><li>Business Requirement Validation</li>
+
+
+<li>Accounting Onboarding</li>
+
+
+<li>Accounting Execution</li>
+
+
+<li>Report Generation</li>
+</ol>
+
+
+<p>To uphold our established principles, we implement checks and balances throughout the stages of financial accounting services:</p>
+
+
+<ol><li>Requirements Signoff </li>
+
+
+<li>Regression Testing</li>
+
+
+<li>Integration Testing</li>
+
+
+<li>UAT Validations<ul><li>Ledger Validations</li>
+
+
+<li>Transaction-Level Validations</li>
+</ul>
+</li>
+
+
+<li>Shadow Validations</li>
+
+
+<li>Deployments<ul><li>Canary</li>
+</ul>
+</li>
+
+
+<li>Health Checks<ul><li>Auditor Checks</li>
+
+
+<li>Completeness Checks</li>
+</ul>
+</li>
+
+
+<li>Alerting/Monitoring</li>
+
+
+<li>Report Generation </li>
+</ol>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-validations-life-cycle-of-accounting-processes-nbsp">Validations Life Cycle of Accounting Processes </h2>
+
+
+<p>As the data flows through various components of the Fintech Systems, there are checks and balances at every stage so that the systems and processes adhere to the tenets.</p>
+
+
+<h3 class="wp-block-heading" id="h-requirements-signoff">Requirements Signoff</h3>
+
+
+<p>Based on the Business Models operating in various countries and the expectations of the local teams, the requirements are provided and tracked. Accounting requirements are provided in accordance with <a href="https://en.wikipedia.org/wiki/Generally_Accepted_Accounting_Principles_(United_States)">Generally Accepted Accounting Principles (GAAP)</a>. The requirements are then onboarded into our accounting systems. Fintech Systems at Uber have internal tools to validate the requirements, which perform 15+ automated checks to validate the expected output. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-regression-testing">Regression Testing</h2>
+
+
+<h3 class="wp-block-heading" id="h-unit-testing">Unit Testing</h3>
+
+
+<p>Unit tests in Uber’s Financial Services are critical for ensuring the accuracy, security, and reliability of our applications. These tests involve isolating small sections of code and verifying the functions as intended. At Uber, we strive to identify and rectify errors early by rigorously testing each unit for correct operation and ensuring overall services–from transaction processing to financial reporting–run smoothly and securely.</p>
+
+
+<h3 class="wp-block-heading" id="h-regression-kaptres">Regression – Kaptres</h3>
+
+
+<p>Kaptre (Capt<s>ure</s> — Re<s>play</s>) is a capture and replay testing tool primarily employed for functional and regression testing purposes. Here’s a breakdown of how our financial systems use its key components:</p>
+
+
+<p><strong>Test Case: </strong>For any accounting change, at least one new Kaptre test is added to the test suite so that all the use cases are tested in successive runs. Each test case includes input (same as used for UAT), expectations, and assertions. </p>
+
+
+<p><strong>Capture Mode: </strong>When adding a test, we operate in “capture mode.” This mode executes the accounting process for the newly added test and captures dependencies needed to re-execute in an offline mode, like API request/responses from upstreams and expected accounting journal entries (JElines). </p>
+
+
+<p><strong>Replay Mode:</strong> The subsequent test runs involve running the Kaptre regression test suite in the replay mode. This mode creates the new output using the latest code/config version and the assertions compare these with the captured expectations. A test failure is reported if the assertion fails.</p>
+
+
+<p><strong>Change Triggers for Captured Responses: </strong>Captured responses change with alterations in upstream systems, new field additions in financial transactions, or anticipated accounting changes. These tests can be updated using the above capture mode after validations. </p>
+
+
+<p>This approach ensures that regression tests accurately reflect the system’s behavior during capture mode and subsequently verifies it against expected outcomes in successive test runs. The design allows for adaptability to changes in upstreams, fintech systems, and anticipated accounting modifications while maintaining the integrity of the testing process and reducing the risk of human error during the testing process.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/KFCn1YyYUZwB8_9hTsWv-M6EyBi-1rlFZuv3vnhyQmXFA2bLDQZ-7EIdWZuU_qteUyF9UBev3u0bJVNoKnQoroZrPcjFFPOcJI_RqNGDs7bIwDInlnZ3_R_CiCFKtbH0RcUwzsceuy9H4mTXpoWwY-Q" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 1: Kaptre (functioning of the capture-replay framework).</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-slate-short-lived-application-testing-environment-nbsp">SLATE (Short-Lived Application Testing Environment) </h3>
+
+
+<p>Testing in a short-lived application environment (a.k.a. SLATE) before deploying to production is a crucial step in Uber’s software development lifecycle. SLATE testing helps us identify and address issues early on and reduces the risk of introducing defects/problems into the production environment. Various types of testing are performed in SLATE, including integration, performance, and security testing. The primary purpose of this testing is to run the application in a production-like environment, identify and detect issues (like runtime errors) early in the development cycle, and prevent the propagation of defects to higher environments.</p>
+
+
+<p>Find more details in the <a href="https://www.uber.com/en-IN/blog/simplifying-developer-testing-through-slate/" target="_blank" rel="noreferrer noopener">Slate Uber Eng Blog</a>.</p>
+
+
+<p>In summary, testing in short-lived application environments is a best practice that contributes to the overall quality, reliability, and security of our services before they are deployed to production.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-integration-testing-nbsp">Integration Testing </h2>
+
+
+<p>Financial Accounting Services at Uber engages with numerous upstream systems (30+) to enrich trip details essential for generating accounting transactions. Integration testing is crucial for seamless communication between financial systems and upstream components, identifying interface issues and enabling early risk mitigation.</p>
+
+
+<p>However, a notable challenge with integration testing lies in determining completeness. Unlike unit tests that have a clear metric for code coverage, integration tests lack insights into the scenarios to cover, and there is no established metric for measuring integration test coverage. This gap results in dependent teams not automatically being informed about new scenarios being launched, and there is a lack of metrics to comprehend test coverage for all scenarios.</p>
+
+
+<p>To address this, we have developed an internal tool that automates the detection, notification, and acknowledgment of the readiness of all dependent systems. This tool aims to ensure a defect-free launch and provides a mechanism to measure integration test coverage.</p>
+
+
+<p>This becomes particularly critical within revenue systems, positioned at the conclusion of the data flow and interacting with multiple services. Unanticipated launches in this context pose the risk of disrupting accounting processes. For instance, a fare launch, lacking proper communication, might be routed to a dead letter queue (DLQ), leading to improper accounting due to insufficient onboarding in the revenue system.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-uat-validations">UAT Validations</h2>
+
+
+<p>User Acceptance Testing (UAT) is a mandatory step in Uber’s financial systems development, where the accounting team rigorously validates financial reports for accuracy. We streamlined this process with comprehensive validation of aggregated and transaction level ledgers through automated testing covering positive and negative scenarios. This ensures integrity of balance sheets, income statements, and other key financial statements. This meticulous approach guarantees seamless integration of updates and patches without disrupting existing functionalities, with over 15 quality checks before signoff.</p>
+
+
+<p>Once accounting configurations are set up as per requirements, then they undergo validation by the Accounting Team, culminating in official sign-off indicating approval and attesting to accuracy and compliance. Business Rule configuration changes adhere to a stringent protocol, requiring explicit authorization from key accounting stakeholders before merging into the main system. Uber utilizes automated Buildkite jobs to ensure integrity and efficiency, systematically checking for necessary approvals when differences in the codebase are identified. This automation reinforces the rigor of the approval process.</p>
+
+
+<p>In instances where changes contradict the established protocols or bypass the mandatory approvals, an automated flag is immediately raised for a thorough review. This safeguard is essential in maintaining the system’s integrity and compliance.</p>
+
+
+<p>Uber’s financial systems employ two primary types of validations to ensure the utmost accuracy and reliability:</p>
+
+
+<ul><li>Sample Validations</li>
+
+
+<li>Ledger Validations</li>
+</ul>
+
+
+<h3 class="wp-block-heading" id="h-sample-validations">Sample Validations</h3>
+
+
+<p>Validations are performed on a selected set of sample orders, which are chosen to be representative of the scenarios of the orders in the production environment. These validations are typically adequate while making incremental changes to the financial systems. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img decoding="async" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Screenshot-2024-04-12-at-2.17.10%E2%80%AFPM-1024x185.png" alt="" class="wp-image-1086095" style="aspect-ratio:5.535135135135135;width:747px;height:auto" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Table 1: Transaction level validations/sample validations.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-ledger-validations">Ledger Validations</h3>
+
+
+<p>For changes that impact a significant number of use cases either at the country or business level, we also perform ledger validations to get completeness assurances. These validations provide additional assurances at aggregate levels over a specific period of time before we implement these changes in production. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Screenshot-2024-04-12-at-2.17.42%E2%80%AFPM-1024x375.png" alt="" class="wp-image-1086096" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Table 2: Aggregate ledger validations.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Both validation types are integral to Uber’s commitment to maintaining the highest standards of financial accuracy and regulatory compliance. They work in tandem to ensure that the financial system remains robust, reliable, and reflective of the true financial position of the company.</p>
+
+
+<h3 class="wp-block-heading" id="h-shadow-validations">Shadow Validations</h3>
+
+
+<p>The purpose of shadow testing is to serve as a final checkpoint to catch any potential issues before the build can be rolled over to the production environment. It’s essentially a build certification strategy aiding in making informed decisions about deploying a release candidate (RC). The core process involves passing production traffic through an RC and comparing its outputs with those from the current production build to spot any anomalies.</p>
+
+
+<p>Shadow testing consists of three parts:</p>
+
+
+<ul><li><strong>Capturing Production Requests</strong>: There are multiple strategies to achieve this. One of those entails recording the (request, response) pairs from production traffic intended for comparison against the RC.</li>
+</ul>
+
+
+<ul><li><strong>Replaying Production Traffic</strong>: These captured requests are replayed against the RC, and the responses are compared to those from the production environment. Any differences are logged for further analysis.</li>
+
+
+<li><strong>Analyzing Differences</strong>: Involves a thorough examination of the logged differences to determine the confidence level of the RC. This step is crucial for certifying the build’s readiness for deployment.</li>
+</ul>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Screenshot-2024-04-12-at-2.18.00%E2%80%AFPM-1024x455.png" alt="" class="wp-image-1086099" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Table 3: Shadow validations between pre-production environment and production environment.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-challenges-and-solutions">Challenges and Solutions</h3>
+
+
+<ul><li><strong>Volume of Traffic and Upstream Calls</strong>: With the fintech services processing over 10K+ events per second, replaying all this traffic against the shadow build is impractical and could result in rate-limiting issues due to numerous upstream calls.</li>
+
+
+<li><strong>Traffic Sampling and Load Distribution</strong>: To mitigate this, we adopt a strategy of sampling a fraction of traffic (e.g., 10%) and distributing the replay over an extended period (e.g., 5 hours). This reduces the calls per second, but also limits the scope of testing.</li>
+</ul>
+
+
+<p>To solve this problem we cache the upstream calls and responses, instead of making real-time network calls.</p>
+
+
+<ul><li><strong>Caching Upstream Calls</strong>: We implemented a caching mechanism for upstream (request, response) pairs to avoid redundant calls during replay, at the cost of increased storage expenses. We minimized the increased storage costs by keeping a retention period of x days post which old data is cleaned up. We always replay against the latest set of data.</li>
+
+
+<li>This approach lacks the ability to detect real-time issues stemming from upstream changes. To mitigate this, we are developing a mechanism for sampling traffic and load distribution.</li>
+</ul>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter is-resized"><img decoding="async" src="https://lh7-us.googleusercontent.com/laVFJXmguJ5XutZD365Hu3SdXUMpGvotZ8HUAA4_OWYtYVcItW3zl7eJoF33tD9jVk1WuvBWkDlP4rQVZnPl75wcf_6mvIqg_Rq_fBR2FJg9hrFbCT-sTPkC1nG6KyTrlSRG-acIn4mPrBWU3OrsuFM" alt="" style="aspect-ratio:1.694915254237288;width:700px;height:auto" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 2: Sampling and storing events for shadow testing.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-replaying-captured-requests">Replaying Captured Requests</h3>
+
+
+<ul><li>A specialized workflow has been developed for replaying stored requests within a given timestamp range against an RC. Discrepancies between the stored responses and the RC’s responses are logged for analysis.</li>
+</ul>
+
+
+<h3 class="wp-block-heading" id="h-validating-and-analyzing-differences">Validating and Analyzing Differences</h3>
+
+
+<ul><li>This phase involves scrutinizing the identified discrepancies. The aim is to differentiate between expected variances and anomalies. This requires an in-depth understanding of the response structure of the Banker system.</li>
+
+
+<li>Banker’s Response Structure: The output from Banker is an array of complex data types called ‘transactions,’ each representing multiple journal entries with attributes like credit, debit, GL account, and line of business.</li>
+</ul>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<figure class="wp-block-image size-large"><img decoding="async" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Screenshot-2024-04-12-at-2.18.19%E2%80%AFPM-1024x459.png" alt="" class="wp-image-1086101" referrerpolicy="no-referrer"></figure>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>The confidence in the build is gauged by how far the monetary discrepancies stray from predefined thresholds. </p>
+
+
+<h3 class="wp-block-heading" id="h-example-scenario-and-analysis">Example Scenario and Analysis</h3>
+
+
+<ul><li><strong>Transaction Comparison:</strong> Transactions from both the primary and shadow builds are compared. Differences are logged in a datastore.</li>
+
+
+<li><strong>Datastore Attributes:</strong> The logged data includes the transactions, their source (primary/shadow), the RunID of the replay workflow, and a timestamp.</li>
+
+
+<li><strong>Detailed Analysis: </strong>We conduct analyses focusing on anomalies in specific areas like LineOfBusiness and GlAccountNumber, using queries to identify monetary discrepancies. The build confidence is adjusted based on these findings.</li>
+</ul>
+
+
+<p>As an example, consider E1 is the event that we processed against Production and release candidates. TxnP is the transaction we got from Production instance and TxnS is the transaction we got from Release Candidate:</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<figure class="wp-block-image size-large"><img decoding="async" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Screenshot-2024-04-12-at-2.18.29%E2%80%AFPM-1024x205.png" alt="" class="wp-image-1086104" referrerpolicy="no-referrer"></figure>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>TxnP and TxnS diff in LineOfBusiness. Hence, we would log them to a datastore for analysis. Our data store will contain four attributes:</p>
+
+
+<ol><li>Transactions -> Array of transactions.</li>
+
+
+<li>Source -> Primary/Shadow. (i.e.) If the transactions are coming from Production or Shadow build.</li>
+
+
+<li>RunID -> RunID of the Replay workflow. Since we can run multiple shadow testing workflows with different builds, we should make sure that we are only analyzing the differences of a specific workflow.</li>
+
+
+<li>Timestamp.</li>
+</ol>
+
+
+<p>Post replaying the E1, our datastore will contain the following two new records:</p>
+
+
+<ol><li>(TxnP, Primary, runID, currentTimeStamp)</li>
+
+
+<li>(TxnS, Shadow, runID, currentTimeStamp)</li>
+</ol>
+
+
+<p>There are multiple ways in which we can analyze these differences. For our use case, we are most interested in capturing any anomalies in LineOfBusiness and GlAccountNumer. Hence, we have written queries that identify the monetary differences between Production and Release candidates across these LOB and GlAccountNumber dimensions. If the monetary difference on credit or debit is beyond a certain threshold, we would reduce the confidence of the build. The farther it strays beyond the threshold, the lower the confidence of the build.</p>
+
+
+<p>For the above example, the shadow testing report for LOB differences will look as follows:</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<figure class="wp-block-image size-large"><img decoding="async" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Screenshot-2024-04-12-at-3.07.22%E2%80%AFPM-1024x166.png" alt="" class="wp-image-1086105" referrerpolicy="no-referrer"></figure>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Consider that we define a threshold of 1,000 USD per line of business. In that case, the difference of 100 is still well below the threshold and hence the confidence of our build would be unaffected.</p>
+
+
+<p>By adopting this shadow testing strategy, you ensure a comprehensive and thorough evaluation of the release candidate. This methodical approach not only identifies potential issues but also provides insights necessary for improving future builds, ultimately contributing to the robustness and reliability of your deployment process.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/lWpk884yU_92bIFwEr29JfVH_HZpEPd6pXf2XMJl1hg42l9JLX39RzczjifWlo9nAjQRFFd9eu54LZgKKOvBigmIohSreFIAK_bTaHqPy_tFpgtQfVpXkS4B256K2gDy_sdQ3BSbP2DHwmAuvKEpAcY" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 3: Shadow testing workflow.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-deployment-nbsp">Deployment </h2>
+
+
+<h3 class="wp-block-heading" id="h-canary-testing-nbsp">Canary Testing </h3>
+
+
+<p>In the financial accounting services at Uber, the builds are deployed daily. To ensure the successful deployment of each build and minimize the impact of issues such as performance degradation, increased error rates, and resource exhaustion, incorporating a canary deployment is crucial. This strategy facilitates a controlled release, preventing immediate impacts on the entire traffic. It enables the identification and resolution of potential issues before a complete deployment occurs.</p>
+
+
+<p>The canary release approach is employed to test real traffic (<=2% traffic) with minimal impact. When a new build is ready for deployment, the canary zone serves as the initial deployment target. If any errors or issues arise during this deployment, the build is not propagated to other production regions, preventing widespread disruption and ensuring a more controlled release process.</p>
+
+
+<h3 class="wp-block-heading" id="h-deployment-monitoring-and-alerting">Deployment monitoring and alerting</h3>
+
+
+<p>The financial accounting service platform consumes data from various upstream sources. To monitor the health of the services, we have configured multiple metrics and alerts. Metrics are tracked and alerts are configured to pause the deployment pipeline and roll it back if we get an alert after deployment for a prescribed period. </p>
+
+
+<h4 class="wp-block-heading" id="h-dead-letter-queues">Dead Letter Queues</h4>
+
+
+<p>DLQ (Dead Letter Queue) stores unprocessed events due to errors. Elevated DLQ counts indicate issues like buggy code, corrupt events, upstream service problems, or rate limiting. Each message queue has a corresponding DLQ for handling unprocessable events. Ideally, the DLQ must have zero events. We use threshold-based alerts for detecting issues and investigating root causes when alerts are triggered. We log all errors, including event details, to a dedicated Apache Kafka<sup>Ⓡ</sup> topic and ingest them into an Apache Hive<sup>TM</sup> table. We have configured Data Studio dashboards for monitoring the Apache Hive<sup>TM</sup> table, providing insights on DLQ events’ impact, count, freshness, and trends. This data-driven approach aids in quickly identifying and prioritizing issues for root cause analysis and system improvement.</p>
+
+
+<h4 class="wp-block-heading" id="h-alerts-and-monitors">Alerts and Monitors</h4>
+
+
+<p>Alerts are primarily used for flagging urgent and critical issues that need to be looked at immediately. Monitors are dashboards on which alerts are configured. The alerts should always be actionable. It is also recommended to tag every alert with a corresponding runbook.</p>
+
+
+<p>Our team alone has around 400+ alerts configured, spanning a wide range of dimensions, including but not limited to DLQ count, consumer lag of message queues, service availability, etc.</p>
+
+
+<h4 class="wp-block-heading" id="h-completeness-checks">Completeness Checks</h4>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/TD2qCI_24RcKTtUAX12d2re1uJHo_00oLC6ItT3kfSvQFwEVGW4P20F71vlxJ_R4GkRxQrkNq7c9sRqGBx18KCfe_FDmGplL4j36asRsFeR8V1MaeKjFRX5zYV6Hx54BT7COj16ZgQI0AxNQh-xGfOA" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 4: Completeness chec</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>All the events received by Financial Services need to be accounted for. When an event is received by our services, it is recorded in the Received Logger. The natural outcomes of processing an event are either of the following</p>
+
+
+<ul><li><strong>Event Processed</strong> – Recorded in Fact Table</li>
+
+
+<li><strong>Event Filtered or Ignored</strong> – Recorded in Filter Logger</li>
+
+
+<li><strong>Event Processing Errored Out</strong> – Recorded in Error Logger</li>
+</ul>
+
+
+<p>To ensure that all incoming events are accounted for, we perform completeness checks. These checks confirm that all events logged in the receive logger are also logged in either the Error logger, Filter logger, or the Fact Table (indicating successful processing).</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-results"><strong>Results</strong></h2>
+
+
+<p>Leveraging the aforementioned testing and detection strategies, our team has achieved a remarkable milestone in 2023: reducing the number of accounting incidents to zero. This significant accomplishment reflects our dedication to accuracy and efficiency in financial management. Furthermore, there has been a notable decrease in manual journal entries, a direct result of diminished accounting errors. This improvement has not only enabled the timely closure of monthly accounting books but has also bolstered our confidence in managing multiple projects within the accounting domain as evidenced by the 17% improvement in throughput. These advancements demonstrate our commitment to excellence and reliability in our accounting practices.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-conclusion"><strong>Conclusion</strong></h1>
+
+
+<p>In conclusion, the comprehensive and multifaceted Fintech Testing Strategies employed by Uber’s Financial Accounting Services (FAS) have proven to be a resounding success. Through rigorous validation processes at every step–from business requirement validation to report generation, and employing advanced techniques such as regression testing, SLATE, integration testing, and shadow validations–Uber has set a new standard in financial systems’ reliability and accuracy.</p>
+
+
+<p>The challenges of handling immense volumes of transactions and data have been met with innovative solutions that not only address current needs but also scale for future growth. The meticulous approach to testing and validation, coupled with deployment strategies like Canary testing and vigilant monitoring and alerting systems, exemplifies Uber’s commitment to maintaining the highest standards in financial technology. In the next year, we are adding even more functionalities to our testing strategies to support the detection and auto-correction of bad inputs to support an error-free self-serve journey.</p>
+
+
+<p>Uber’s journey in refining its Fintech Testing Strategies serves as a benchmark for others in the industry, underlining the importance of continuous innovation and rigorous testing in the ever-evolving landscape of financial technology.</p>
+https://www.uber.com/blog/accounting-data-testing-strategies/https://www.uber.com/blog/accounting-data-testing-strategies/Thu, 18 Apr 2024 05:00:00 GMTUberEngineeringMigrating a Trillion Entries of Uber’s Ledger Data from DynamoDB to LedgerStore<h1 class="wp-block-heading" id="h-introduction">Introduction</h1>
+
+
+<p>Last week, we explored <a href="https://www.uber.com/blog/how-ledgerstore-supports-trillions-of-indexes/" target="_blank" rel="noreferrer noopener">LedgerStore</a> (LSG) – Uber’s append-only, ledger-style database. This week, we’ll dive into how we migrated Uber’s business-critical ledger data to LSG. We’ll detail how we moved more than a trillion entries (making up a few petabytes of data) transparently and without causing disruption, and we’ll discuss what we learned during the migration. </p>
+
+
+<h3 class="wp-block-heading" id="h-history">History</h3>
+
+
+<p>Gulfstream is Uber’s payment platform. It was <a href="https://www.uber.com/blog/payments-platform" target="_blank" rel="noreferrer noopener">launched in 2017</a> using DynamoDB for storage. At Uber’s scale, DynamoDB became expensive. Hence, we started keeping only 12 weeks of data (i.e., hot data) in DynamoDB and started using Uber’s blobstore, TerraBlob, for older data (i.e., cold data). TerraBlob is similar to AWS S3.</p>
+
+
+<p>For a long-term solution, we wanted to use <a href="https://www.uber.com/blog/dynamodb-to-docstore-migration/" target="_blank" rel="noreferrer noopener">LSG</a>. It was purpose-built for storing payment-style data. Its key features are:</p>
+
+
+<ul><li>It is verifiably immutable (i.e., you can check that records have not been altered using cryptographic signatures)</li>
+
+
+<li>Tiered storage to manage cost (the hot data is kept at a place that is best to serve requests and cold data is stored at a place that is optimized for storage)</li>
+
+
+<li>Better lag for eventually consistent secondary indexes</li>
+</ul>
+
+
+<p>So, by 2021, Gulfstream was using a combination of DynamoDB, TerraBlob, and LSG to store data.</p>
+
+
+<ul><li>DynamoDB for the last 12 weeks of data</li>
+
+
+<li>TerraBlob, Uber’s internal blob store, for cold data</li>
+
+
+<li>LSG, where we were writing data, and wanted to migrate to it</li>
+</ul>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-why-migrate">Why Migrate?</h2>
+
+
+<p>LSG is better suited for storing ledger-style data because of its immutability. The recurring cost savings by moving to LSG were significant.</p>
+
+
+<p>Going from three to a single storage would simplify the code and design of the Gulfstream services responsible for interacting with storage and creating indexes. This in turn makes it easy to understand and maintain the services.</p>
+
+
+<p>LSG promised shorter indexing lag (i.e., time between when a record is written and its secondary index is created). Additionally, it would give us faster network latency because it was running on-premises within Uber’s data centers.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/ImSq9jhPp_-uGFsvBU0tmJA1MiY42lmKUH1fLoNJ036l2w7W9uLx89xRnBO30l7lRkHXQ0XQv_flDWeZB0pfRyYzczFfayP_Vi4j217OZt8fG5WxpM2FKdt3lB34s0emy0gp6nUKNfS2q7MR5z8ZUbc" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 1: Data flow before and after the migration</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-nature-of-data-amp-associated-risk">Nature of Data & Associated Risk</h2>
+
+
+<p>The data we were migrating is all of Uber’s ledger data for all of Uber’s business since 2017:</p>
+
+
+<ul><li>Immutable records – 1.2 PB compressed size</li>
+
+
+<li>Secondary indexes – 0.5 PB uncompressed size</li>
+</ul>
+
+
+<p>Immutable records should not be modified. So, for all practical purposes, once we have written a record, it can’t be changed. We do have the flexibility of modifying secondary index data for correcting problems.</p>
+
+
+<h2 class="wp-block-heading" id="h-checks">Checks</h2>
+
+
+<p>To ensure that the backfill is correct and acceptable in all respects, we need to check that we can handle the current traffic and the data that is not being accessed currently is correct. The criteria for this was:</p>
+
+
+<ul><li>Completeness: All the records were backfilled.</li>
+
+
+<li>Correctness: All the records were correct.</li>
+
+
+<li>Load: LSG should be able to handle current load.</li>
+
+
+<li>Latency: The P99 latency of LSG was within acceptable bounds.</li>
+
+
+<li>Lag: The secondary indexes are created in the background. We want to make sure that the delay of the index creation process was within acceptable limits.</li>
+</ul>
+
+
+<p>The checks were done using a combination of <em>shadow validation</em> and <em>offline validation</em>.</p>
+
+
+<h3 class="wp-block-heading" id="h-shadow-validation">Shadow Validation</h3>
+
+
+<p>This compares the response that we had been returning before migration with the one that we would return with the LSG as data source. This helps us ensure that our current traffic will be disrupted by neither data migration issues nor code bugs. We wanted our backfill to be at least 99.99% complete and correct as measured by shadow validation. We also had a 99.9999% upper bound for the same. The reason for having an upper bound are:</p>
+
+
+<ul><li>When migrating historical data, there are always data corruption issues. Sometimes this is because data was not written correctly during the initial development time of the service. It is also possible to see data corruption because of scale. As an example, S3 gives 11 nines of durability guarantee then you can expect 10 corruptions in 1 trillion records.</li>
+
+
+<li>Indexes are eventually consistent, which means that some records will appear after a few seconds. So, the shadow validation will flag them as missing. This is a false positive that shows up at a large scale.</li>
+
+
+<li>For 6 nines, you have to look at data of 100 million comparisons to give any results with good confidence. This means if your shadow validation is comparing 1,000 records/second, then you need to wait for a bit more than one day just to collect sufficient data. With 7 nines, you will have to wait 12 days. In practical terms this would slow the project to a halt.</li>
+
+
+<li>With a well-defined upper bound, you are not forced to look at every potential issue that you suspect. Say if the occurrence of a problem is 1/10 of the upper bound, you need not even investigate it.</li>
+
+
+<li>With 6 nines, we could end up with slightly more than 1 million corrupt records. Even though 6 nines of confirmed correctness could mean a real cost to the company, the savings generated by this project outweighed the potential cost.</li>
+</ul>
+
+
+<p>During shadow validation you are essentially duplicating production traffic on LSG. So by monitoring LSG, we can verify that it can handle our production traffic while meeting our latency and lag requirements. It gives us good confidence in the code that we wrote for accessing the data from LSG. Additionally, it also gives us some confidence about completeness and correctness of data, particularly with data that is currently being accessed. We developed a single generic shadow validation code that was reused multiple times for different parts of the migration.</p>
+
+
+<p>During the migration process we found latency and lag issues because of multiple bugs in different parts and fixed them.</p>
+
+
+<ul><li>Partition key optimization for better distribution of index data</li>
+
+
+<li>Index issues causing scan of the record instead of point lookup</li>
+</ul>
+
+
+<p>Unfortunately, live shadow validation can’t give strong guarantees about our corpus of rarely-accessed historical data.</p>
+
+
+<h3 class="wp-block-heading" id="h-offline-validation-amp-incremental-backfill">Offline Validation & Incremental Backfill</h3>
+
+
+<p>This compares complete data from the LSG with the data dump from DynamoDB. Because of various data issues, you have to skip over bad records to ensure that your backfill can go through. Additionally, there can be bugs in the backfill job itself. Offline validation ensures that the data backfill has happened correctly and it covers complete data. This has to be done in addition to shadow validation because live traffic tends to access only recent data. So, if there are any problems lurking in the cold data that is infrequently accessed, it will not be caught by shadow validation. </p>
+
+
+<p>The key challenge in offline validation is size of data. The biggest data that we tackled was 70 TB compressed (estimated 300 TB uncompressed) in size and we compared 760 billion records in a single job. This type of Apache Spark<sup>TM</sup> job requires data shuffling and <a href="https://www.uber.com/blog/ubers-highly-scalable-and-distributed-shuffle-as-a-service/">Distributed Shuffle as a Service for Spark</a> combined with Dynamic Resource Allocation and Speculative Execution let us do exactly that at a reasonable speed under resource constraints.</p>
+
+
+<p>Offline validation found missing records and its output was used for incremental backfill. We iterated between offline validation and backfill to ensure that all the records were written. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-backfill-issues">Backfill Issues</h2>
+
+
+<p>Every backfill is risky. We used Uber’s internal offering of Apache Spark for the backfills. Here are the different problems that we encountered and how we handled them.</p>
+
+
+<h3 class="wp-block-heading" id="h-scalability">Scalability</h3>
+
+
+<p>You want to start at a small scale and scale up gradually till you hit the limit of the system. If you just blindly push beyond this point then you are effectively creating a DDoS attack on your own systems. At this point, you want to find the bottleneck, address it, and then scale up your job. Most of the time it’s just a matter of scaling up downstream services, other times it can be something more complex. In either case, you don’t want to scale your backfill job beyond the capability of the bottleneck of the system. It’s a good idea to scale up in small increments and monitor closely after each scale-up.</p>
+
+
+<h3 class="wp-block-heading" id="h-incremental-backfills">Incremental Backfills</h3>
+
+
+<p>When you try to backfill 3 years’ worth of data in say 3 months, you are generating traffic that puts 10x the normal traffic load and the system may not be able to cope with this traffic. As an example, you will need 120 days to backfill 100B records at 10K/sec rate when your production normally handles 1K/sec rate. So, you can expect the system to get overloaded. If there is even a remote chance of the backfill job causing an ongoing problem, you must shut it down. So, it is unrealistic to expect that a backfill job can run from start to finish in one go, and therefore you have to run backfills incrementally.</p>
+
+
+<p>A simple and effective way to do this is to break the backfill into small batches that can be done one by one, such that each batch can complete within a few minutes. Since your job may shut down in the middle of a batch, it has to be idempotent. Every time you complete a batch you want to dump the statistics (such as records read, records backfilled, etc.) to a file. As your backfill continues, you can aggregate numbers from them to check the progress.</p>
+
+
+<p>If you can delete or update existing records, it lowers the risk and cost of mistakes and code bugs during the backfill.</p>
+
+
+<h3 class="wp-block-heading" id="h-rate-control">Rate Control</h3>
+
+
+<p>To backfill safely, you want to make sure that your backfill job behaves consistently. So, your job should have rate control that can be easily tweaked to scale up or scale down. In Java/Scala you can use Guava’s RateLimiter.</p>
+
+
+<h3 class="wp-block-heading" id="h-dynamic-rate-control">Dynamic Rate Control</h3>
+
+
+<p>In some cases, you may be able to go faster when there is less production traffic. For this you need to monitor the current state of the system and see if it’s ok to go faster. We adjusted RPS on the lines of <a href="https://en.wikipedia.org/wiki/Additive_increase/multiplicative_decrease" target="_blank" rel="noreferrer noopener">additive increase/multiplicative decrease</a>. We still had an upper bound on the traffic for safety.</p>
+
+
+<h3 class="wp-block-heading" id="h-emergency-stop">Emergency Stop</h3>
+
+
+<p>The migration process needs the ability to stop backfill quickly in case there is an outage or even suspicion of overload. Any backfill during an outage has to be stopped as both a precaution and as a potential source of noise. Even post-outage, systems tend to get extra load as systems recover. Having the ability to stop backfill also helps debug scale-related issues.</p>
+
+
+<h3 class="wp-block-heading" id="h-size-of-data-file">Size of Data File</h3>
+
+
+<p>When dumping data, keep the size of the files to around 1GB with 10x flexibility on both sides. If the size of the file is too big, you run into issues such as <a href="https://kb.databricks.com/cloud/s3-part-number-limit.html" target="_blank" rel="noreferrer noopener">MultiPart limitation of different tools</a>. If your file size is small, then you have too many files and even listing them will take significant time. You may even start hitting ARGMAX limit of when running commands in a shell. This becomes significant enough to make sure that every time you do something with data it has been applied to all files and not just some of them.</p>
+
+
+<h3 class="wp-block-heading" id="h-fault-tolerance">Fault Tolerance</h3>
+
+
+<p>All backfill jobs need some kind of data transformation. When you do this you inevitably run into data quality/corruption issues. You can’t stop the backfill job every time this happens because such bad records tend to be randomly distributed. But you can’t ignore them as well because it might also be because of a code bug. To deal with this, you dump problematic records separately and monitor statistics. If the failure rate is high then you can stop the backfill manually, fix the problem, and continue. Otherwise, let the backfill continue and look at the failures in parallel.</p>
+
+
+<p>Another reason for records not getting written is RPC timeout. You can retry for this, but at some point, you have to give up and move ahead irrespective of the reason to make sure you can make progress.</p>
+
+
+<h3 class="wp-block-heading" id="h-logging">Logging</h3>
+
+
+<p>It is tempting to log during backfill to help with debugging and monitor progress, but this may not be possible because of the pressure that it will put on the logging infrastructure. Even if you can keep logs, there will be too much log data to keep around. The solution is to use a rate limiter to limit the amount of logs that you are producing. You need to rate limit only the parts that produce most of the logs. You can even choose to log all the errors if they happen infrequently.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/xWcB-v0gyFB4920hZx1tevZiHiSLhUKPvA7TZMvkCN6bsEmh5bZiTcZ0xYumbfjsgsG6Oz-Xnl85XeLhD4ofUc07poJ1OnsB4WlNCEyZzYmY9kuvfgCkSxzC4nSvqcBEmYQvANytw4oOyXA4wyQDias" alt="" referrerpolicy="no-referrer"></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-mitigating-risk">Mitigating Risk</h2>
+
+
+<p>In addition to analyzing data from different validation and backfill stats we also were conservative with the rollout of LSG. We rolled it out over a few weeks and with go-aheads from on-call engineers of the major callers of our service. We initially rolled out with fallback (i.e., if the data was not found in LSG, we would try to fetch it from DynamoDB). We looked at the fallback logs before we removed the fallback. For every record that was flagged as missing in the fallback logs we checked LSG to make sure that it was not really missing. Even after that we kept the DynamoDB data around for a month before we stopped writing data to it, took a final backup, and dropped the table.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/P7cnF5dxZX7H5rA82nfZgC1ICBQX7Q928jAexep0GBSR39-B2kDw44hHTtEQQuBNmqw9ZeFz_KYY39uqlUBSEErrb2XWhWagcpWKrsb8tiDX_6CYfOXACQst7Wak7mIewxy4WvI3gW3Vza3altpn0Tc" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 2: LSG Rollout</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-conclusion">Conclusion</h1>
+
+
+<p>In this article, we covered the migration of massive amounts of business-critical money data from one datastore to another. We covered different aspects of the migration, including criteria for migration, checks, backfill issues, and safety. We were able to do this migration over two years without any downtime or outages during or after the migration.</p>
+
+
+<h3 class="wp-block-heading" id="h-acknowledgments">Acknowledgments</h3>
+
+
+<p>Thanks to Amit Garg and Youxian Chen for helping us migrate the data from TerraBlob to LSG. Thanks to Jaydeepkumar Chovatia, Kaushik Devarajaiah, and Rashmi Gupta from the LSG team for supporting us throughout this work. Thanks to Menghan Li for migrating data for <a href="https://www.uber.com/en-EG/blog/cashless-payments-with-uber-cash/" target="_blank" rel="noreferrer noopener">Uber Cash</a>’s ledger.</p>
+
+
+<p class="has-small-font-size">Cover photo attribution: “<a href="https://www.flickr.com/photos/51986662@N05/51912457870">Waterfowl Migration at Sunset on the Huron Wetland Management District</a>” by <a href="https://www.flickr.com/photos/51986662@N05">USFWS Mountain Prairie</a> is marked with <a href="https://creativecommons.org/publicdomain/mark/1.0/?ref=openverse">Public Domain Mark 1.0</a>.</p>
+
+
+<p class="has-small-font-size">Amazon Web Services, AWS, the Powered by AWS logo, [and name any other AWS Marks used in such materials] are trademarks of Amazon.com, Inc. or its affiliates.</p>
+
+
+<p class="has-small-font-size">Apache®, Apache SparkTM, and SparkTM are either registered trademarks or trademarks of the Apache Software Foundation in the United States and/or other countries. No endorsement by The Apache Software Foundation is implied by the use of these marks.</p>
+https://www.uber.com/blog/migrating-from-dynamodb-to-ledgerstore/https://www.uber.com/blog/migrating-from-dynamodb-to-ledgerstore/Thu, 11 Apr 2024 05:30:00 GMTUberEngineeringHow LedgerStore Supports Trillions of Indexes at Uber<h1 class="wp-block-heading" id="h-introduction">Introduction</h1>
+
+
+<p>Uber connects the physical and digital worlds to help make movement happen at the tap of a button. Billions of trips, deliveries, and tens of billions of financial transactions across earners, spenders, and merchants are made at Uber every quarter. LedgerStore is an immutable storage solution at Uber that provides verifiable data completeness and correctness guarantees to ensure data integrity for these transactions.</p>
+
+
+<p>Considering that ledgers are the source of truth of any financial event or data movement at Uber, it is important to be able to look up ledgers from various access patterns via indexes. This brings in the need for <strong>trillions</strong> of indexes to index hundreds of billions of ledgers. A previous <a href="https://www.uber.com/en-US/blog/dynamodb-to-docstore-migration/" target="_blank" rel="noreferrer noopener">blog post</a> discussed the background of LedgerStore and how the storage backend was re-architected. This blog covers the significance of LedgerStore indexing and its architecture, which powers trillions of indexes, with a petabyte-scale index storage footprint.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-types-of-indexes">Types of Indexes</h1>
+
+
+<p>Various types of indexes need to be supported on ledgers. Let us explore them along with corresponding use cases.</p>
+
+
+<h2 class="wp-block-heading" id="h-strongly-consistent-indexes">Strongly consistent indexes</h2>
+
+
+<p>One of the use cases is handling the credit card authorization flow when a rider/eater uses Uber. At the beginning of an Uber trip, a credit card hold is placed on the rider/eater’s credit card. This hold should either be converted to a charge or voided, depending on whether the trip was taken or canceled, as shown below. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="618" src="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig1-e1711742633458.png" alt="" class="wp-image-1084314" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig1-e1711742633458.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig1-e1711742633458.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig1-e1711742633458.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig1-e1711742633458.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=1539,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig1-e1711742633458.png 1539w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 1: Uber Trip credit-card payment flow supported by strongly consistent indexes.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>If the index serving the hold is not strongly consistent<em>, </em>it could take a while for the hold to be visible upon reading. A consequence of this is that a duplicate charge could be made on the user’s credit card while the original hold remains on the credit card. </p>
+
+
+<p>Now, let’s dive into how we build strongly consistent indexes that ensure that once a record write is performed, any subsequent reads are guaranteed to see the indexes corresponding to that record.</p>
+
+
+<h3 class="wp-block-heading" id="h-write-path">Write Path</h3>
+
+
+<p>To build strongly consistent indexes, we use a 2-phase commit to ensure that the index is always strongly consistent with the record, as shown below. </p>
+
+
+<p>The insert operation begins with an index intent write before the record write. These intents are committed after the record write operation if the record write succeeded and this is done asynchronously to avoid affecting end-user insert latency. If the index intent write succeeds, but the record write fails, the index intent will need to be rolled back, else it leads to an accumulation of unused intents, and that is handled during the read time, as we will see next. </p>
+
+
+<p>It is important to note that if the index intent write fails, the whole insert operation fails since we cannot guarantee the consistency of the index with the record. Hence, strongly consistent indexes need to be considered only when the use case strongly demands it. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="520" src="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig2-e1711742801993.png" alt="" class="wp-image-1084320" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig2-e1711742801993.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig2-e1711742801993.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig2-e1711742801993.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1260,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig2-e1711742801993.png 1260w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 2: Two-phase commit write flow of strongly consistent indexes.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-read-path">Read Path</h3>
+
+
+<p>There are two cases where an index can be in the intent state after the insert: </p>
+
+
+<ol><li>The index intent commit operation failed in the write path OR </li>
+
+
+<li>If record write fails</li>
+</ol>
+
+
+<p>Such intents are handled on the read path by either committing or deleting them. When a read happens on these indexes, if the index is in an intent state, the corresponding record is read. If the record is present, the index is committed, else rolled back. These operations happen asynchronously so as not to affect the end user read latency. In general, only a very small percentage of indexes end up in the intent state.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="791" src="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig3-e1711742960693.png" alt="" class="wp-image-1084321" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig3-e1711742960693.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig3-e1711742960693.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig3-e1711742960693.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1180,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig3-e1711742960693.png 1180w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 3: Read flows of strongly consistent indexes.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-eventually-consistent-indexes">Eventually consistent indexes</h2>
+
+
+<p>Not all indexes require strong read-your-write guarantees. An example of such an index is the payment history page, wherein, a lag of a few seconds is acceptable as long as the payment appears on the page.</p>
+
+
+<p>While strongly consistent indexes provide <em>read-your-write</em> guarantees, they are not suitable in certain circumstances since they trade off the following properties to achieve this guarantee:</p>
+
+
+<ul><li><strong>Higher Write Latency</strong><br>Since the index intent write operation and corresponding record write has to be serial to provide a strong consistency guarantee of the index for the record</li>
+
+
+<li><strong>Lower Availability</strong><br>A write failure of any one of the index intents implies the whole write should be failed else indexes will not be consistent with the corresponding record</li>
+</ul>
+
+
+<p>Eventually, consistent indexes are the opposite in this aspect when compared to strongly consistent indexes, as they are built in the background by a separate process that is completely isolated from the online write path. Hence, they do not suffer from <em>higher write latency</em> or cause potential <em>lower availability</em> of LedgerStore service. We leverage a feature called Materialized Views from our home-grown <a href="https://www.uber.com/blog/schemaless-sql-database/" target="_blank" rel="noreferrer noopener">Docstore</a> database to generate these indexes.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="990" src="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig4-e1711743013811.png" alt="" class="wp-image-1084322" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig4-e1711743013811.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig4-e1711743013811.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig4-e1711743013811.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig4-e1711743013811.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=1820,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig4-e1711743013811.png 1820w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 4: Payment history served by eventually consistent indexes.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-time-range-indexes">Time-range indexes</h2>
+
+
+<p>Ledgers, due to their immutable nature, keep growing in size over time, thereby increasing their cost of storage. So, at Uber, we offload older ledgers in time-range batches to cheaper cold storage. </p>
+
+
+<p>Every ledger is associated with a timestamp called a business or event timestamp. To offload ledgers to cold storage (and also for sealing the data), we need a class of indexes to query data in event time-range batches. What differentiates this index is that the data is read in deterministic time-range batches, in orders of magnitude higher than the above two index types.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" width="1020" height="591" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig5-e1711743069138.png" alt="" class="wp-image-1084325" style="aspect-ratio:1.7258883248730965;width:701px;height:auto" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1020,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig5-e1711743069138.png 1020w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig5-e1711743069138.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig5-e1711743069138.png 768w" sizes="(max-width: 1020px) 100vw, 1020px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 5: time-range indexes used in data-tiering.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Following is an example of how time-range queries are done on ledgers:</p>
+
+
+<figure class="wp-block-table"><table><tbody><tr><td><strong>SELECT * FROM</strong> LEDGER_TABLE <strong>WHERE</strong> LedgerTime <strong>BETWEEN</strong> 1701252000000 <strong>AND</strong> 1701253800000</td></tr></tbody></table></figure>
+
+
+<figure class="wp-block-table"><table><tbody><tr><td><strong>Ledger</strong></td><td><strong>LedgerTime</strong></td></tr><tr><td>{trip started}</td><td>10:01 am</td></tr><tr><td>{trip completed and fare adjusted}</td><td>10:15 am</td></tr><tr><td>{post trip corrections}</td><td>12:01 pm</td></tr></tbody></table></figure>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>There are a few ways to model this in a distributed database. We will dive into the key differences between developing the time-range index on top of Amazon DynamoDB vs. Docstore database. Both DynamoDB and Docstore, being distributed databases, provide data modeling constructs as Partition and Sort keys. The former is meant for distributing data across partitions evenly based on its value and the latter to control the sort order of the data. </p>
+
+
+<h3 class="wp-block-heading" id="h-design-with-dynamodb">Design with DynamoDB</h3>
+
+
+<p>Dynamodb provides two ways of managing table read/write <a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html" target="_blank" rel="noreferrer noopener">capacity</a>. We used the provisioned mode since the traffic is not too <a href="https://docs.aws.amazon.com/wellarchitected/latest/serverless-applications-lens/capacity.html" target="_blank" rel="noreferrer noopener">bursty</a> to require on-demand mode. The provisioned mode was configured with <a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html" target="_blank" rel="noreferrer noopener">auto scaling</a> to adjust capacity based on the traffic pattern. </p>
+
+
+<p>As we notice from the write pattern above, the ledger times are generally correlated to the current wall clock time. Hence these values tend to be clustered around the current time. If we were to partition the data based on say <strong>G</strong> time-units granularity, all the writes in the <strong>G</strong> time-units would go to the same physical partition causing hot partitions. DynamoDB has restrictions on throughput in case of <a href="https://aws.amazon.com/blogs/database/choosing-the-right-dynamodb-partition-key/" target="_blank" rel="noreferrer noopener">hot partitions</a>, leading to throttling of write requests, which is not acceptable in the online write path. Assuming 1K peak Uber trips/s, even G=1 second is not a good value, since it corresponds to 1K WCU (Write Capacity Unit), which is the peak allowed QPS before <a href="https://aws.amazon.com/blogs/database/choosing-the-right-dynamodb-partition-key/" target="_blank" rel="noreferrer noopener">throttling</a> happens. </p>
+
+
+<p>While it might seem like we could just make the partitioning more fine-grained, it is still not foolproof, since an increase in the traffic over time can lead to instability. Another side effect of this is the increase in cumulative reads to be performed via a scatter-gather. So, what we did in the case of DynamoDB was below:</p>
+
+
+<h4 class="wp-block-heading" id="h-write-optimized-temporary-index-table-called-buffer-index">Write-optimized temporary index table (called buffer index)</h4>
+
+
+<p>All online time-index writes go to the buffer index table. Inserted index items are partitioned into <strong><em>M</em></strong> unique buckets based on a hash modulo of the corresponding record to <a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-partition-key-design.html" target="_blank" rel="noreferrer noopener">uniformly distribute</a> load across partitions in the buffer index table, making it <em>write-efficient</em>. The value of <strong><em>M</em></strong> is chosen such that it is high enough that the amount of load per partition avoids excessive splitting. It is also chosen low enough, to limit the amount of scatter-gather<em> </em>to perform during reads. </p>
+
+
+<h4 class="wp-block-heading" id="h-read-optimized-permanent-index-table">Read-optimized permanent index table</h4>
+
+
+<p>The need for scatter-gathe<em>r </em>read of the buffer tables makes them not efficient for reads and since reads can happen throughout the lifecycle of a table, we would need to optimize it. This brings the need for a read-efficient permanent index table. </p>
+
+
+<p>A permanent time-range index table is partitioned on the timestamp aligned to a certain time duration <strong><em>N</em></strong> (say 10 minutes). Indexes from the buffer tables are periodically written in batches to the permanent index table. Since the write is done in batches and in the background, any write throttling here does not affect the online traffic. Another advantage of batching is that the write traffic can be distributed across partitions, reducing the hot partitioning. The buffer index tables are deleted after offloading their indexes to the permanent index table since they are no longer needed. Reads on the permanent index tables are done in intervals of <strong><em>N</em></strong> minutes without any scatter-gather, making this table <em>read-efficient</em>.<br><br>Following is a depiction of the time-range index flow in case of DynamoDB. The dual table design brings in the need of state management and coordination so reads go to the correct index table as well.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="920" height="1024" src="https://blog.uber-cdn.com/cdn-cgi/image/width=920,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig6-e1711743514668.png" alt="" class="wp-image-1084328" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=920,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig6-e1711743514668.png 920w, https://blog.uber-cdn.com/cdn-cgi/image/width=269,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig6-e1711743514668.png 269w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig6-e1711743514668.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1380,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig6-e1711743514668.png 1380w, https://blog.uber-cdn.com/cdn-cgi/image/width=1499,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig6-e1711743514668.png 1499w" sizes="(max-width: 920px) 100vw, 920px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 6: Time-range index design on Dynamodb.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-design-with-docstore">Design with Docstore</h3>
+
+
+<p>The two-table design in the case of DynamoDB functions well and can handle high throughput, but introduces challenges in operations. If the temporary buffer tables are not created in time, it can lead to write failure since writes cannot be accepted, and this has caused availability issues in the past. We re-architected our index storage backend from DynamoDB to Uber’s <a href="https://www.uber.com/blog/schemaless-sql-database/" target="_blank" rel="noreferrer noopener">Docstore</a> database as part of cost efficiency. As part of this re-architecture, we also improved the time-range index design to overcome the downside of maintaining two tables, by leveraging two Docstore properties:</p>
+
+
+<ol><li><a href="https://www.uber.com/blog/schemaless-sql-database/" target="_blank" rel="noreferrer noopener">Docstore</a> is a distributed database built on top of MySQL, with a fixed number of shards assigned to a variable number of physical partitions. As the data size grows, the number of physical partitions increases and some of the existing shards are re-assigned to the new partitions, leading to a max upper<strong> limit</strong> to the number of physical partitions. </li>
+
+
+<li>Data in Docstore is stored in a <strong>sorted</strong> fashion of the primary key (partition + sort keys).</li>
+</ol>
+
+
+<p>We maintain just one table for the time-range index, wherein the index entries are partitioned on the full timestamp value. Since the timestamp is extremely granular, there is no hot partitioning (and hence no write throttling) since most of the writes are uniformly distributed across partitions.</p>
+
+
+<p>Reads involve a prefix scanning of each of the shards of the table up to a certain time granularity. Prefix scanning is very similar to a regular scan of the table, except the boundaries of each scan request are controlled by the application. So, in the example below, to read 30 minutes worth of data, reads could be done on a 10-minute interval starting from 2023–02-03 01:00:00 to 2023–02-03 01:10:00 and similarly repeated for the next two sub-windows. Since data is sorted on the primary key, this prefix scan with given boundaries ensures only data lying within these timestamps is read. </p>
+
+
+<p>A scatter-gather, followed by sort merging across shards is then performed to obtain all time-range index entries in the given window, in a sorted fashion. Since the number of shards is fixed in Docstore, we can precisely determine (and bound) the number of read requests that need to be performed. The same technique is not applicable in the case of DynamoDB since the number of partitions keeps increasing over time, as the table size increases. This has significantly simplified the design and reduced the operational maintenance cost of our time-indexes. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="914" src="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig7-e1711743568767.png" alt="" class="wp-image-1084329" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig7-e1711743568767.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig7-e1711743568767.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig7-e1711743568767.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1080,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig7-e1711743568767.png 1080w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 7: Time-range index design on Docstore.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-index-lifecycle-management">Index lifecycle management</h2>
+
+
+<p>New indexes are defined regularly and some of the indexes could be modified as well to evolve use cases. To support that with minimal effort and also not cause any regressions, we need a mechanism to manage the index lifecycle. The following are the components of the same:</p>
+
+
+<h3 class="wp-block-heading" id="h-index-lifecycle-state-machine">Index lifecycle state machine</h3>
+
+
+<p>This component orchestrates the life-cycle of the index, involving creating the index table, backfilling it with historical index entries, validating them for completeness, swapping the old index with the new one for read/writes, and decommissioning the old index.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="375" src="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig8-e1711743614440.png" alt="" class="wp-image-1084330" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig8-e1711743614440.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig8-e1711743614440.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig8-e1711743614440.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig8-e1711743614440.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=1800,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig8-e1711743614440.png 1800w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 8: Index lifecycle state machine.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-historical-index-data-backfill">Historical Index data backfill</h3>
+
+
+<p>Depending on the business use cases, new indexes need to be defined, and it is essential to backfill historical index entries so that they are complete. This component builds indexes from the historical data offloaded to the cold data storage and backfills them to the storage layer in a scalable fashion. Considering that the data download speed is higher than the data processing speed, this component is built with configurable rate-limiting and batching in a reusable way, since we can plug in the actual processing logic as a batch processor plugin.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="592" src="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig9-e1711743676584.png" alt="" class="wp-image-1084331" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig9-e1711743676584.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig9-e1711743676584.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig9-e1711743676584.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1420,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig9-e1711743676584.png 1420w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 9: Historical data processing module customized to backfill indexes.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-index-validation">Index validation</h3>
+
+
+<p>After indexes are backfilled, they need to be verified for completeness. This is done by an offline job that computes order independent checksums at a certain time-window granularity and compares them across the source of truth data and the index table. This step identifies any bugs in the index backfill process since even if one entry is missed, the aggregate checksum for that time window will lead to a mismatch.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="350" src="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig10-e1711743725757.png" alt="" class="wp-image-1084332" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig10-e1711743725757.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig10-e1711743725757.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig10-e1711743725757.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig10-e1711743725757.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=1640,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/04/Fig10-e1711743725757.png 1640w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 10: Index completeness validation.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-highlights">Highlights</h2>
+
+
+<p>This is how we measured the success of this critical project:</p>
+
+
+<ul><li>We built over 2 trillion unique indexes, and not a single data inconsistency has been detected so far, with the new architecture in production for over 6 months.</li>
+
+
+<li>Not a single production incident was noticed during the backfill, given how critical money movement is for Uber.</li>
+
+
+<li>We also moved all these indexes from DynamoDB to Docstore. So the project also resulted in technology consolidation, reducing external dependencies.</li>
+</ul>
+
+
+<p>From a business impact perspective, operating LedgerStore is now very cost-effective due to reduced spend on DynamoDB. The estimated yearly savings are over $6 million per year.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-conclusion">Conclusion</h1>
+
+
+<p>Ledgers are the source of truth for money movement events at Uber. The robust indexing platform we have built supports accessing these sources of truth ledgers for various business use cases, and we look forward to supporting many more indexes on this platform in the future. </p>
+
+
+<p>We would like to conclude with some key takeaways: Maintaining a petabyte-scale of indexes in an OLTP system brings in certain challenges, such as imbalanced partitioning, high read/write amplification, noisy neighbor problems, etc. So data modeling and isolation are important aspects to consider while designing these systems. Further, depending on the actual database used underneath for storage, the design methodology can be significantly different, as we see from the design contrast of time-range indexes on two different distributed databases.</p>
+
+
+<p>Join us next week to see part two of the LedgerStore series where we chronicle a migration from DynamoDB to LedgerStore.</p>
+
+
+<h2 class="wp-block-heading" id="h-acknowledgments">Acknowledgments</h2>
+
+
+<p>This project would not have been possible without collaboration from the following teams, embodying several <a href="https://www.uber.com/in/en/careers/values/" target="_blank" rel="noreferrer noopener">Uber values</a>:</p>
+
+
+<ul><li>The <a href="https://www.uber.com/blog/payments-platform/" target="_blank" rel="noreferrer noopener">Gulfstream</a> team, who closely worked with the LedgerStore team in aligning on the common goals and migrating on the LedgerStore platform, a multi-year project.</li>
+
+
+<li>The Docstore team, for evolving <a href="https://www.uber.com/en-IN/blog/schemaless-sql-database/" target="_blank" rel="noreferrer noopener">Docstore</a> to meet the massive scale requirements of LedgerStore’s indexes.</li>
+
+
+<li>The LedgerStore team for leading, building, and driving the adoption of ledger indexes at large scale.</li>
+</ul>
+
+
+<p class="has-small-font-size"><em>Amazon Web Services, AWS, the Powered by AWS logo, and Amazon DynamoDB are trademarks of Amazon.com, Inc. or its affiliates.</em></p>
+https://www.uber.com/blog/how-ledgerstore-supports-trillions-of-indexes/https://www.uber.com/blog/how-ledgerstore-supports-trillions-of-indexes/Thu, 04 Apr 2024 05:30:00 GMTUberEngineeringBackendData / MLScaling AI/ML Infrastructure at Uber<h1 class="wp-block-heading" id="h-introduction"><strong>Introduction</strong></h1>
+
+
+<p>Machine Learning (ML) is celebrating its 8th year at Uber since we first started using complex rule-based machine learning models for driver-rider matching and pricing teams in 2016. Since then, our progression has been significant, with a shift towards employing deep learning models at the core of most business-critical applications today, while actively exploring the possibilities offered by Generative AI models. As the complexity and scale of AI/ML models continue to surge, there’s a growing demand for highly efficient infrastructure to support these models effectively. Over the past few years, we’ve strategically implemented a range of infrastructure solutions, both CPU- and GPU-centric, to scale our systems dynamically and cater to the evolving landscape of ML use cases. This evolution has involved tailored hardware SKUs, software library enhancements, integration of diverse distributed training frameworks, and continual refinements to our end-to-end Michaelangelo platform. These iterative improvements have been driven by our learnings along the way, and continuous realignment with industry trends and Uber’s trajectory, all aimed at meeting the evolving requirements of our partners and customers.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-goal-and-key-metrics"><strong>Goal and Key Metrics</strong></h2>
+
+
+<p>As we embarked on the transition from on-premise to cloud infrastructure that we <a href="https://www.wsj.com/articles/uber-signs-cloud-deals-with-google-and-oracle-b45a9372" target="_blank" rel="noreferrer noopener">announced</a> in February 2023, our HW/SW co-design and collaboration across teams was driven by the specific objectives of: </p>
+
+
+<ol><li>Maximizing the utilization of current infrastructure</li>
+
+
+<li>Establishing new systems for emerging workloads, such as Generative AI</li>
+</ol>
+
+
+<p>In pursuit of these goals, we outlined distinct key results and metrics that guide our progress.</p>
+
+
+<p><strong>Feasibility and Reliability:</strong> ML users expect successful convergence of their training tasks without errors within an expected time frame (either weeks or months based on complexity). For instance, training larger and more complex models like Falcon 180B™ can take many months, and longer training durations heightened the likelihood of reliability issues. Hence, our target is to achieve 99% uptime SLA for all training dependencies to ensure consistent and reliable outcomes.</p>
+
+
+<p><strong>Efficiency:</strong> Our focus on efficiency involves thorough benchmarking of diverse GPU configurations and assessing price-performance ratios of on-prem and cloud SKUs tailored to specific workloads. We gauge training efficiency using metrics like Model Flops Utilization (MFU) to guarantee optimal GPU utilization. Our aim is to prevent idle GPUs, opportunistically using training jobs during serving’s off-peak hours through reactive scaling, and upholding high utilization rates to maximize resource efficiency. We want to do this while also maintaining fairness of resource sharing between different users. </p>
+
+
+<p><strong>Developer Velocity:</strong> This metric is quantified by the number of experiments our engineers can conduct within a specific timeframe. We prioritize a mature ecosystem to bolster developer velocity, ensuring our teams work efficiently to deliver optimal solutions. This approach not only streamlines our state-of-the-art model to production but also reduces the time taken for this transition.</p>
+
+
+<p>What follows next is a summary of results from various initiatives that we are taking to make training and serving deployments efficient and scalable, across both on-prem and cloud infrastructure: </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-optimizing-existing-on-prem-infrastructure"><strong>Optimizing Existing On-prem Infrastructure</strong></h2>
+
+
+<h3 class="wp-block-heading" id="h-federation-of-batch-jobs"><br>Federation of Batch Jobs:</h3>
+
+
+<p>Our GPU assets are distributed over multiple <a href="https://kubernetes.io/" target="_blank" rel="noreferrer noopener">Kubernetes</a>™ clusters in various Availability Zones and Regions. This distribution is primarily due to GPU availability and the node count limitation within a single Kubernetes cluster. This arrangement presents two primary challenges:</p>
+
+
+<ol><li>Exposure of infrastructure specifics to Machine Learning Engineers.</li>
+
+
+<li>Inconsistent resource utilization across clusters due to static allocation. Although we have an effective resource-sharing system within each cluster, we lacked the capability for inter-cluster scheduling.</li>
+</ol>
+
+
+<p>To address these issues, we created a unified federation layer for our batch workloads, including <a href="https://www.ray.io/" target="_blank" rel="noreferrer noopener">Ray</a>™ and Apache <a href="https://spark.apache.org/" target="_blank" rel="noreferrer noopener">Spark</a>™, called <strong>Michelangelo Job Controller</strong>. This component serves as a centralized interface for all workload scheduling, conceals the underlying Kubernetes clusters, and allocates workloads based on various policies (load aware, bin-pack), including compute and data affinity considerations. We plan to share more technical details on this in a subsequent blog post.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/BQBvxC9TSCSgAj8ZlAAL8Dkydbx3B__KT9nHfrs7eUfLEU6CVUiGo4uG6QUmWkJ0piVRdwkjSioJ-Q80JmKI7pFzlHOEssw3DTZlou544_4uJkyYHdbC55OkKSQfq7ZyL9x8yN8iuZ6a8Hv5RMg0-xk" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Fig 1: Unified federation layer for ML workload allocation.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-network-upgrade-for-llm-training-efficiency">Network Upgrade for LLM training efficiency</h3>
+
+
+<p>When expanding infrastructure to accommodate Generative AI applications and enhancing the efficiency of distributed training while fine-tuning open-source LLMs, it is important to focus on scaling network bandwidth across both scale-up and scale-out configurations. This necessitates implementing critical features such as full mesh <a href="https://www.nvidia.com/en-us/design-visualization/nvlink-bridges/" target="_blank" rel="noreferrer noopener">NVlink</a>™ connectivity among GPUs, upgrades in network link speeds, proficient congestion control management, QoS controls, and the establishment of dedicated rack and network topologies, among other essential features.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="593" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Fig2_network_upgrade-1024x593.png" alt="" class="wp-image-1083848" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Fig2_network_upgrade.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Fig2_network_upgrade.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Fig2_network_upgrade.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Fig2_network_upgrade.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Fig2_network_upgrade.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Fig2: Training efficiency improvements through network link capacity upgrades.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>We present a synopsis of findings derived from a Large Language Model (LLM) case study, emphasizing the considerable impact of enhanced network bandwidth and congestion control mechanisms on training effectiveness and price-performance efficiency. Our observations revealed nearly a two-fold increase in training speed and substantial reductions in training duration when employing higher networking bandwidth and better congestion control mechanisms compared to our existing network interconnect. During multi-node training, duplicating data across nodes heightens local memory demands and adds to IO workload. Our analysis prompted a recommendation to augment network link capacity by 4x (25GB/s to 100GB/s) on each GPU server, potentially doubling the available training capacity. While building these we also need to make sure the “Elephant Flows” generated by the large training runs don’t negatively impact the other high-priority service by proper isolation and QoS controls.</p>
+
+
+<h3 class="wp-block-heading" id="h-memory-upgrade-to-improve-gpu-allocation-rates"><br>Memory Upgrade to improve GPU allocation rates</h3>
+
+
+<p>Newer AI/ML workloads are demanding more system memory per GPU worker than what we had designed for. The inherent physical constraints, such as the limited number of memory channels on each server, and DIMM capacities deployed during NPI (new product introduction) restricted our ability to scale up GPU allocations. To improve our GPU allocation rates, we have initiated an effort to double the amount of memory on these servers (16GB to 32GB per DIMM channel). Additionally, we are also building a framework to repurpose and reuse the DIMM’s when older racks are decommissioned. Such optimizations allow us to maximize utilization of existing ML infrastructure and make the most of our current resources. We will detail the efficiency gains achieved through this initiative in an upcoming post. In parallel, we have kicked off efforts to help rightsize the training jobs’ resource requirements. As demonstrated by others [<a href="https://tianyin.github.io/pub/amp.pdf" target="_blank" rel="noreferrer noopener">ref</a>], manually requesting the optimal resources is a hard problem, and automating it would help in increasing the allocation efficiency. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-building-new-infrastructure"><strong>Building New Infrastructure</strong></h2>
+
+
+<h3 class="wp-block-heading" id="h-price-performance-evaluations-across-various-cloud-skus"><br>Price-performance evaluations across various cloud SKUs</h3>
+
+
+<p>In late 2022 as we embarked on our journey towards transitioning to the cloud, we assessed various CPU and GPU models offered by different cloud providers. Our aim was to compare their price-performance ratios using established benchmarks ranging from tree-based and deep learning to large language models alongside proprietary datasets and Uber’s models such as deepETA and deepCVR. These assessments, conducted for both training and serving purposes, enabled us to select the most suitable SKUs optimized for our specific workloads, considering factors like feasibility, cost, throughput, and latency. Throughout 2023, we extensively tested 17 different GPU and CPU SKUs, employing various libraries and optimizers, including Nvidia’s <a href="https://github.com/NVIDIA/TensorRT" target="_blank" rel="noreferrer noopener">TensorRT</a>™(TRT) and TRT-LLM optimizations. For instance, as depicted in figures 4 and 5, we found that while A10 GPUs might not offer the most cost-effective throughput for training tasks, they prove to be the optimal choice for our serving use cases, delivering the best throughput while maintaining acceptable SLA using TRT.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/6lE7W5fYhVSHGudF-A9Fu6wzvEQo4-S7ZjnN8dSgy3HcTmC4pqn-RT9VvBF0kTwZYY3rCz6OU4BVQfZ5erhWA2UMlK-7VbUYQkqKF6SUb58hKjHdzbzH7GK6Do40TLNw7bg0GTxgQYgzQDDV-jbkXxg" alt="" title="Chart" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Fig 3: Deep learning training and serving performance-price evaluation.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/jnlRbG2pls4P0xjxD9Pvv7fx4BW5_ZWXtSYLQLXfN317i1lPtxJPOxT6xbzNT8OIHEtAXarcDNNFeC-YRUAI0zh4t1sTBuPUfYeppJPdIwMpPDDJ7E8ddXBnNqde1rCZZVxCJiCIbpQ1qWd4oIGWyhk" alt="" title="Chart" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Fig 4: Deep learning serving latency with and without TensorRT optimizations.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Numerous Generative AI applications at Uber necessitate the use of Nvidia’s newest H100 GPUs to satisfy their stringent latency requirements. This requirement stems from the H100 GPUs’ capabilities, which include up to 4x TFlops and double the memory bandwidth compared to the earlier generation A100 GPUs. While experimenting with Meta™ <a href="https://llama.meta.com/" target="_blank" rel="noreferrer noopener">Llama2</a>™ model series, involving various batch sizes, quantizations, and model parameters, we evaluated various open- and closed-source frameworks to further optimize for LLM serving performance. In Figures 6 and 7, we present a specific case where we employ two metrics: per-token latency (ms/token) and tokens/sec/gpu, to evaluate and compare the model’s performance across two of the top-performing frameworks (TRT-LLM and a currently confidential framework), keeping all other parameters constant and using FP16 quantization. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/qs9gWGpDUlhVZrug3qN88E-xDt8PKhA0Rd-R_WL8ECGq-DG50lJ7rz1nT37PxgIRyM0k2ypyN2Aq4v_FTnve8_tq9ayMOkm4cRd0UoTzSYbalhD2CDKQINp5F8uxVVDS8Y1ol-1MeKZK3pGzcSfd4dw" alt="" title="Chart" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Fig 5: LLM serving latency comparison by framework (H100).</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/rhL0z9GvoYxR0yiwFONGfGaHXsFNo_kORbuXeb9b2c8M0NEe_jJCbeEDThJUVHc05NeSt84xDjN7m5Skd2SvbzfHTUyz-MaaEhAffQoBtuKe3k7RZPVDQFDk7ZsgMYyFXfwCX-wL2dldeo2tHYzce-A" alt="" title="Chart" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Fig 6: LLM serving throughput comparison by framework using the same latency budget and minimum number of GPUs required (H100).</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>These experiment results clearly demonstrate that Framework B delivers a two-fold increase in latency and a six-fold improvement in throughput compared to TRT-LLM. It further underscores the significance of HW/SW co-design and that to fully leverage hardware capabilities, it is essential to have the right solutions across the entire stack.</p>
+
+
+<h3 class="wp-block-heading" id="h-llm-training-efficiency-improvements-with-memory-offload"><br>LLM Training efficiency improvements with memory offload</h3>
+
+
+<p>In this section, we outline our framework for design and experimentation regarding the placement of optimizer states, parameters and gradients from GPU memory to either CPU memory or NVMe devices for large language models. Our aim is to evaluate how this offload impacts GPU scalability, training efficiency, and a range of system metrics. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="637" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Fig6_memory_offload_design_space-1024x637.png" alt="" class="wp-image-1083850" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Fig6_memory_offload_design_space.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Fig6_memory_offload_design_space.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Fig6_memory_offload_design_space.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Fig6_memory_offload_design_space.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Fig6_memory_offload_design_space.png 2048w, https://blog.uber-cdn.com/cdn-cgi/image/width=2120,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Fig6_memory_offload_design_space.png 2120w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Fig 7: Design framework for memory offload experimentation.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Our experiment results demonstrated that our capacity to train expansive models previously hindered by restricted GPU memory has been significantly enhanced. Memory offloading from GPU memory to system memory or even NVMe devices helped in boosting training efficiency by enabling the utilization of larger batch sizes with the same number of GPUs. This shift has resulted in a 2x increase in MFU (model flops utilization) while concurrently reducing GPU usage by 34%. However, it’s noteworthy that this improvement comes with a corresponding reduction in network throughput. A detailed open-computer project (<a href="https://www.opencompute.org/" target="_blank" rel="noreferrer noopener">OCP</a>) conference talk on this topic can be found <a href="https://www.youtube.com/watch?v=Ju0r8yU1_Lw" target="_blank" rel="noreferrer noopener">here</a>. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/L8HJjzd4fJLc0rv2q8ArOqvVbN-mlHlKwGTqoYg6dPciNtvU6kjAn3NK3eVfjp1WdeqLgJu2zIhmRNxeM5vkX3E47bIRNezH-X9ytjOWzh7lRI0V9OFtZMzOtUbaZXJjf6HsXy4oznVON7V6JTQt7zc" alt="" title="Chart" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Fig 8: Training efficiency implementing deepspeed memory offload optimization.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-conclusion"><strong>Conclusion</strong></h1>
+
+
+<p>To conclude, we’d like to leave you with three key insights. Designing a singular AI/ML system amid rapid application and model advancements, spanning from XGboost to deep learning recommendation models and large language models, poses considerable challenges. For instance, while LLMs demand high TFlops, deep learning models can encounter memory limitations. To enhance the cost-effectiveness of these systems, exploring workload-optimized solutions based on efficiency metrics like cost-to-serve and performance per dollar within a given SLA becomes imperative. Maximizing infrastructure efficiency necessitates a collaborative hardware and software design approach across all layers of the system. Within this context, we’ve showcased various examples in this post, illustrating how to leverage existing infrastructure effectively while building new capabilities to efficiently scale the infrastructure. Lastly, we extend an invitation to foster industry partnerships, urging engagement in open-source optimizations to drive efficiency and exchange ideas and learnings on effectively scaling infrastructure to tackle the evolving demands of the AI landscape.</p>
+
+
+<h2 class="wp-block-heading" id="h-acknowledgments"><strong>Acknowledgments </strong></h2>
+
+
+<p>Many thanks for the collaboration on the above work to the UBER AI Infrastructure, OCI, GCP, and Nvidia team members. </p>
+
+
+<p class="has-small-font-size">Apache®, Apache Kafka, Kafka, Apache Spark, Spark, and the star logo are either registered trademarks or trademarks of the Apache Software Foundation in the United States and/or other countries. No endorsement by The Apache Software Foundation is implied by the use of these marks.</p>
+
+
+<p class="has-small-font-size">Kubernetes® and its logo are registered trademarks of The Linux Foundation® in the United States and other countries. No endorsement by The Linux Foundation is implied by the use of these marks.</p>
+
+
+<p class="has-small-font-size">Falcon 180B® and its logo are registered trademarks of Technology Innovation Institute™ in the United States and other countries. No endorsement by Technology Innovation Institute is implied by the use of these marks.</p>
+
+
+<p class="has-small-font-size">LLaMA 2® and its logo are registered trademarks of Meta® in the United States and other countries. No endorsement by Meta is implied by the use of these marks.</p>
+https://www.uber.com/blog/scaling-ai-ml-infrastructure-at-uber/https://www.uber.com/blog/scaling-ai-ml-infrastructure-at-uber/Thu, 28 Mar 2024 07:28:34 GMTUberEngineeringAIData / MLModel Excellence Scores: A Framework for Enhancing the Quality of Machine Learning Systems at Scale<h1 class="wp-block-heading" id="h-introduction">Introduction</h1>
+
+
+<p>Machine learning (ML) is integral to Uber’s operational strategy, influencing a range of business-critical decisions. This includes predicting rider demand, identifying fraudulent activities, enhancing Uber Eats’ food discovery and recommendations, and refining estimated times of arrival (ETAs). Despite the growing ubiquity and impact of ML in various organizations, evaluating model “quality” remains a multifaceted challenge. A notable distinction exists between online and offline model assessment. Many teams primarily focus on offline evaluation, occasionally complementing this with short-term online analysis. However, as models become more integrated and automated in production environments, continuous monitoring and measurement are often overlooked.</p>
+
+
+<p>Commonly, teams concentrate on performance metrics such as AUC and RMSE, while neglecting other vital factors like the timeliness of training data, model reproducibility, and automated retraining. This lack of comprehensive quality assessment leads to limited visibility for ML engineers and data scientists regarding the various quality dimensions at different stages of a model’s lifecycle. Moreover, this gap hinders organizational leaders from making fully informed decisions regarding the quality and impact of ML projects.</p>
+
+
+<p>To bridge this gap, we propose defining distinct dimensions for each phase of a model’s lifecycle, encompassing prototyping, training, deployment, and prediction (See Figure 1). By integrating the Service Level Agreement (SLA) concept, we aim to establish a standard for measuring and ensuring ML model quality. Additionally, we are developing a unified system to track and visualize the compliance and quality of models, thereby providing a clearer and more comprehensive view of ML initiatives across the organization. Note that Model Excellence Scores (MES) cover certain technical aspects that are integral to Uber’s overall ML governance.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/isX-qlXXKvyRNL8ZrqG7ecOuLg3MzE-EeDYMT1JdrdIESlDE_PMXJcc7hHT0c4496eN18aSxij2pX5zVCRTGiovjtyGurwVEV9w1jaX-YUq2hj1huPJQM39GmLqyOlzl-HPxfhC8YP5Lp2KTLhlunbw" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 1: Example ML quality dimensions (in yellow) in a typical ML system.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-model-excellence-scores-mes">Model Excellence Scores (MES)</h2>
+
+
+<p>The development and maintenance of a production-ready ML system are intricate, involving numerous stages in the model lifecycle and a complex supporting infrastructure. Typically, an ML model undergoes phases like feature engineering, training, evaluation, and serving. The infrastructure to sustain this includes data pipelines, feature stores, model registries, distributed training frameworks, model deployment, prediction services, and more.</p>
+
+
+<p>To offer a comprehensive evaluation of model quality across these phases, we created and introduced the Model Excellence Scores (MES) framework. MES is designed to measure, monitor, and enforce quality across each stage of the ML lifecycle. This framework aligns with principles and terminologies common among site reliability engineers (SREs) and DevOps professionals, particularly those used in managing microservices reliability in production environments.</p>
+
+
+<p>MES revolves around three fundamental concepts related to Service Level Objectives (SLOs): indicators, objectives, and agreements. Indicators are precise quantitative measures reflecting some aspect of an ML system’s quality. Objectives set target ranges for these indicators, and agreements combine all indicators at an ML use case level, dictating the overall PASS/FAIL status based on the indicator results.</p>
+
+
+<p>Each indicator in MES is clearly defined and has a set target range for its metric value, with a specified frequency for value updates. If an indicator falls short of its objective within a given time frame, it’s marked as failing. Agreements, which encapsulate these indicators, represent the commitment level of the service and provide insights into its performance. Figure 2 illustrates the interconnections between agreements, indicators, and objectives, and how they relate to specific use cases and models.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/bvZ0Oj6F3DG-ZDLprNYgODtxB444TWmjTAEMqNlVxgeozimoLuFjXa6m6LVCKCAE7CrTaDD6t2SgvAUUPUmEQaYMe8bbfDOtMgsn10i2W1A3AtQemO7gpOORuYiFTPkjMhIst_8t9RtlITBHxK-dWWw" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 2: Relationship among agreement, indicator, objective, use cases, and models.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Different indicators might necessitate varied timeframes for resolution and distinct mitigation strategies. Some may require immediate attention with higher priority handling, especially when performance benchmarks are not met. </p>
+
+
+<p>It’s also important to note that the roles and responsibilities associated with modeling can vary significantly between organizations. In some cases, a single team may handle the entire process, while in others, responsibilities may be distributed across multiple teams or departments.</p>
+
+
+<p>At Uber, the responsibility for each model is assigned to a designated primary team. This team receives alerts for any discrepancies or issues related to their model, as outlined in the agreement. Teams have the flexibility to tailor these alerts based on the significance and urgency of their ML use cases. It’s important to note that the quality of one model can influence another, either directly or indirectly. For instance, the output from one model might serve as input for another or trigger further model evaluations. To address this interconnectedness, we’ve implemented a notification system that informs both service and model owners of any quality violations in related ML models.</p>
+
+
+<p>The interaction between the Model Excellence Scores (MES) framework and other ML systems at Uber is depicted in Figure 3. The MES framework, with its indicators, objectives, and agreements, is built on several key principles:</p>
+
+
+<ul><li><strong>Automated Measurability</strong>: Every indicator in MES is designed with metrics that can be quantified and automated, ensuring robust infrastructure for instrumentation.</li>
+
+
+<li><strong>Actionability</strong>: Indicators are not just measurable but also actionable. This means that there are clear steps that users or the platform can take to improve these metrics over time in relation to their set objectives.</li>
+
+
+<li><strong>Aggregatability</strong>: The metrics for each indicator are capable of being aggregated. This is crucial for effective reporting and monitoring, allowing for a cohesive roll-up of metrics in line with the organization’s Objectives and Key Results (OKRs) and Key Performance Indicators (KPIs).</li>
+
+
+<li><strong>Reproducibility</strong>: Metrics for each indicator are idempotent, meaning their measurements remain consistent when backfilled.</li>
+
+
+<li><strong>Accountability</strong>: Clear ownership is attached to each agreement. The designated owner is responsible for defining the objectives and ensuring these objectives are achieved.</li>
+</ul>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/QJtG_get-AGg37qbai6tkDE1-x9IXbOt28Xsk4tFbSBV6mGfC5jt0aOXtPOEAQpP3RIK8JiQuc2-B-HTUquxWMh0LAqWelYAIesr2YJ2z1cT9-UyyaAOaD_GHGt8iN2BY8Vj2IHOhECetrh84AZU9Tg" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 3: High-level view of the interaction between the MES framework and various ML systems.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>We focus on some indicators that haven’t been extensively covered in related literature in Table 1. MES is capable of measuring aspects like fairness and privacy, these topics are out of scope of this discussion. We’ve outlined in the table below how each indicator adheres to these design principles, providing examples of measurable metrics, actionable steps for improvement, and the normalization schemes applied to ensure that the metrics are aggregatable and consistent across different use cases. These metrics are either normalized to a [0,1] scale, converted to a percentage, or maintained on a consistent scale across various applications.</p>
+
+
+<figure class="wp-block-table"><table><thead><tr><th>Indicators</th><th>Description</th><th>Possible Actions</th><th>Metric Normalization</th></tr></thead><tbody><tr><td>Data Quality</td><td>Measures the quality of the input datasets used to train the model. This is a compost score for: <br>– Feature null<br>– Cross-region consistency<br>– Missing Partiitions<br>– Duplicates</td><td>– Backfill the missing partitions<br>– Sync the data partitions across different regions and instances<br>– De-duplicate the rows in the data</td><td>Each component in the composite score is normalized to the percentage scale</td></tr><tr><td>Dataset Freshness</td><td>Measures the freshness of the input datasets used to train the model</td><td>– Retrain with fresh input datasets<br>– Backfill input datasets if updated data is available</td><td>Scale-consistent</td></tr><tr><td>Feature and Concept Drift</td><td>Shift in the target and covariate distribution as well as the relationship between the two over time for a model in production</td><td>– Apply weighted training or retrain the model with fresh data<br>– Validate the correctness of upstream feature ETL pipelines</td><td>Normalized to [0,1] by using normalized distance metric and importance weights</td></tr><tr><td>Model Interpretability</td><td>Measures the presence and confidence of robust feature explanations for each prediction generated by the model</td><td>– Enable explanations</td><td>Normalized to [0,1]</td></tr><tr><td>Prediciton Accuracy</td><td>Prediction accuracy of the model on production traffic (e.g., AUC, normalized RMSE)</td><td>– Update training datasets to account for train-serve skew<br>– Check for feature or concept drift</td><td>Normalized to [0,1] by normalizing the accuracy metric</td></tr></tbody></table><figcaption class="wp-element-caption">Table: Sample of indicators.</figcaption></figure>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-results">Results</h2>
+
+
+<p>The implementation of the MES framework at Uber has markedly enhanced the visibility of ML quality within the organization. This increased transparency has been instrumental in fostering a culture that prioritizes quality, subsequently impacting both business decisions and engineering strategies. Over time, we have observed substantial progress in adherence to SLAs across various dimensions. Notably, there has been a remarkable 60% improvement in the overall prediction performance of our models.</p>
+
+
+<p>Moreover, the insights gleaned from the MES metrics have been pivotal in identifying areas for platform enhancements. A key development arising from these insights was the introduction of advanced platform tooling for hyperparameter tuning. This innovation enables the automatic periodic retuning of all models, streamlining the optimization process and ensuring consistent model performance. Such improvements underscore the tangible benefits of the MES framework in driving both operational efficiency and technological advancement</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-lessons-learned">Lessons Learned</h2>
+
+
+<p>In our journey of implementing and monitoring key indicators across all ML teams at Uber, we’ve gleaned several critical insights.</p>
+
+
+<p><strong>Motivating ML Practitioners:</strong> The established framework allowed for a tangible measurement of the impact and efforts directed toward quality improvements. By adopting a standard and transparent reporting system, we created an environment where ML practitioners were motivated to enhance quality, knowing that their efforts were visible and recognized across the organization.</p>
+
+
+<p><strong>Alignment and Executive Support:</strong> Initially, quality measures could be perceived as an additional burden unless they are seamlessly integrated into everyday practices from the outset. Implementing a quality tracking framework sheds light on existing gaps, necessitating extra efforts in education and awareness to address these issues. Aligning with executive leadership was crucial, enabling teams to prioritize quality-focused tasks. This alignment gradually led to a shift towards a more proactive, quality-centric culture across the board.</p>
+
+
+<p><strong>Balancing Standardization with Customization:</strong> In designing the framework, we aimed for a level of standardization that would allow for consistent tracking and informed decision-making over time. However, given Uber’s diverse ML applications, it was also vital to permit customization for specific indicators to accurately reflect the nuances of each use case. For instance, in ETA prediction models, we adopted mean-average-error as a more contextual metric than RMSE. The framework accommodated such customizations while maintaining a standardized approach to reporting for consistency.</p>
+
+
+<p><strong>Prioritizing Incremental Improvements:</strong> Managing the framework across a wide array of use cases posed significant challenges in prioritization. We developed a straightforward prioritization matrix to identify which areas needed immediate attention. Recognizing that a handful of models contribute most to the impact, our focus was on enhancing quality in high-impact use cases first.</p>
+
+
+<p><strong>The Role of Automation:</strong> Maintaining ML quality is resource-intensive, and manually managing models in production can divert efforts from innovation. Automating the production lifecycle, including retraining, revalidating, and redeploying models with fresh data, proved invaluable. This automation not only enhanced model freshness (as indicated by the reduced average age of models), but also allowed teams to focus more on innovation and less on maintenance.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-conclusion">Conclusion</h1>
+
+
+<p>We have developed a comprehensive framework that outlines the key dimensions of high-quality machine learning (ML) models across different stages of their lifecycle. This framework is inspired by Service Level Agreement (SLA) principles and is designed to monitor and ensure the quality of ML models. Importantly, it’s structured to accommodate additional quality dimensions, adapting to emerging use cases and evolving best practices in the field.</p>
+
+
+<p>Our discussion also encompassed the application of this framework in generating insightful quality reports at various levels of the organization. These reports are regularly reviewed, fostering accountability and offering valuable insights for strategic planning. Crucially, by embedding ML quality within the overall service quality of the associated software systems, we’ve facilitated a shared responsibility model. Applied scientists, ML engineers, and system engineers now collectively own ML quality. This collaborative approach has significantly bridged the gap between these functions, fostering a proactive, quality-focused culture within the organization.</p>
+
+
+<h3 class="wp-block-heading" id="h-acknowledgments">Acknowledgments</h3>
+
+
+<p>We could not have accomplished the technical work outlined in this article without the help of our team of engineers and applied scientists at Uber. We would also like to extend our gratitude to the various Technical Program Managers – Gaurav Khillon, Nayan Jain, and Ian Kelley – for their pivotal role in promoting the adoption and compliance of the MES framework across different organizations at Uber.</p>
+https://www.uber.com/blog/enhancing-the-quality-of-machine-learning-systems-at-scale/https://www.uber.com/blog/enhancing-the-quality-of-machine-learning-systems-at-scale/Thu, 21 Mar 2024 05:30:00 GMTUberEngineeringData / MLBalancing HDFS DataNodes in the Uber DataLake<h1 class="wp-block-heading" id="h-introduction"><strong>Introduction</strong></h1>
+
+
+<p>Apache Hadoop<sup>Ⓡ</sup> Distributed File System (HDFS) is a distributed file system designed to store large files across multiple machines in a reliable and fault-tolerant manner. It is part of the Apache Hadoop framework and is one of the main components of Uber’s data stack.</p>
+
+
+<p>Uber has one of the largest HDFS deployments in the world, with exabytes of data across tens of clusters. It is important, but also challenging, to keep scaling our data infrastructure with the balance between efficiency, service reliability, and high performance.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/VaaufGJF2NoMmsAXqw0SjcSbkWbdPFm1-Kr_ZYFuHKKoFGozTrx0QEhYCk2vu7lAd8vai59XYBhIssXwY0LfI5kWh7AQGTKKYTM34rWx8Re1V8U7gEI0Z0O_vLgXLXT8af8frAQNJJQ_95n95isTgWw" alt="" referrerpolicy="no-referrer"></figure>
+
+
+<p> Figure 1: HDFS Infrastructure at Uber.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-overview"><strong>Overview</strong></h1>
+
+
+<p>HDFS balancer is a key component to keep DataNodes healthy by redistributing data evenly in the cluster. The HDFS balancer has to balance data more effectively to prevent DataNode skew as our HDFS clusters have more and more intensive node decommissioning. The node decommission requirement comes from projects such as zone decommissioning, automatic cluster turnover for security patch, and also DataNode colocation.</p>
+
+
+<p>However, the balancer that comes with HDFS open source did not meet this requirement out of the box. We have seen issues of one DataNode being skewed (i.e., storing more data compared to other nodes in the same cluster), which has multiple side effects:</p>
+
+
+<ul><li>Leads to high I/O bandwidth on the host containing too much data</li>
+
+
+<li>Highly utilized nodes have a higher probability of slowness, higher risk of node failure, data loss</li>
+
+
+<li>Cluster has fewer active and healthy nodes to serve writing traffic for customers</li>
+</ul>
+
+
+<p>Below is an example of unbalanced data: thousands of nodes are near 95% disk utilization in our largest cluster composed of thousands of DataNodes with hundred PBs of capacity, while the balancing throughput can’t move data effectively to the other newly added DataNode. Such unbalanced data distribution is caused by bursty write traffic from warm tiering and EC conversion[1], intensive node decommission from zone decom/cluster turnover for security patch. As the write reliability is the first priority, all DataNodes serve write traffic together with an available capacity-weighted algorithm. With more write traffic, data skews more as well.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="212" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-2-Argon-cluster-original-1024x212.png" alt="" class="wp-image-1082498" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-2-Argon-cluster-original.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-2-Argon-cluster-original.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-2-Argon-cluster-original.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-2-Argon-cluster-original.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=1999,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-2-Argon-cluster-original.png 1999w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 2: One of our biggest clusters comprising around thousands of DataNodes with hundred PBs of capacity has skewed DataNodes.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Thus, we need to optimize the HDFS balancer to increase the data balance from the high-usage DataNode to another, less occupied DataNode.</p>
+
+
+<p>Given the scale of data storage at Uber, there would be more than 20 PB of data-unbalanced nodes in a single cluster, with 7-8 clusters. To tackle this problem of balancing HDFS DataNodes in the Uber DataLake, we devised a new algorithm to increase the number of pairs formed between DataNodes, which would increase parallel block movements while balancing data. Also, we did sort DataNodes based on utilization such that the datanode pairs formed are optimized and no recursive balancing takes place.</p>
+
+
+<p>This algorithm would go on to increase our throughput for balancing i.e. size of data moved per second from a higher occupied datanode to a lower occupied datanode considered for balancing.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-architecture-amp-design"><strong>Architecture & Design</strong></h2>
+
+
+<div class="wp-block-image"><figure class="aligncenter is-resized"><img decoding="async" src="https://lh7-us.googleusercontent.com/aypCjNKWlTTa6yQzeGj53GgpowcKkI2Sowy6KlqoObWeWb2sGt7QrR7AS5AEk8kjzHKseHi4zEbcG_HW31QNaglL96kh-0RzVIhXk8qVLmLMJbr5Qr_yULMeF-HVYBCBwknrf3UCeY1RRaNRv8vyLIk" alt="" style="aspect-ratio:1.2903225806451613;width:701px;height:auto" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 3: HDFS Balancer Architecture.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<ol><li>Initialization and Setup:<ol><li>The HDFS balancer is run on a host as a service within the Hadoop cluster.</li>
+
+
+<li>To initiate the balancing process, a node with a balancer role needs to be present in the cluster. No two balancers can run concurrently.</li>
+</ol>
+</li>
+
+
+<li>Requesting Cluster Information:<ol><li>The balancer first contacts the NameNode to request information about the data distribution within the cluster. It sends a request to the NameNode to obtain details about the distribution of data blocks across DataNodes.</li>
+
+
+<li>The NameNode responds with a list of DataNodes and the blocks they contain, along with their storage capacities and other relevant information.</li>
+</ol>
+</li>
+
+
+<li>Block Selection and Planning:<ol><li>Based on the information received from the NameNode, the balancer algorithm selects blocks that need to be moved to achieve a more balanced distribution.</li>
+
+
+<li>The balancer takes into consideration factors such as DataNode utilization, rack information, threads, and storage capacity while planning block movements.</li>
+</ol>
+</li>
+
+
+<li>Coordination of Data Movement:<ol><li>After determining which blocks to move, the balancer coordinates the actual data movement between DataNodes.</li>
+
+
+<li>It communicates with the NameNode regarding the blocks moved with the help of heartbeats.</li>
+</ol>
+</li>
+
+
+<li>Block Migration:<ol><li>The balancer initiates block migration by communicating directly with the source and destination DataNodes.</li>
+
+
+<li>It instructs the source DataNode to transfer the selected block to the destination DataNode, moving the data block directly.</li>
+</ol>
+</li>
+
+
+<li>Monitoring Progress:<ol><li>Throughout the data movement process, the balancer continuously monitors progress. It keeps track of how many blocks have been successfully transferred and ensures that the data movement is proceeding according to the plan.</li>
+</ol>
+</li>
+
+
+<li>Completion and Reporting:<ol><li>Once the balancing operation is complete, the balancer reports the data transferred and data left to transfer in logs and through metrics.</li>
+
+
+<li>It may also provide statistics and metrics about the balancing process, including the number of blocks moved and the time taken.</li>
+</ol>
+</li>
+
+
+<li>Termination:<ol><li>In the host, the balancer runs as a service. So, until the cluster is balanced, it won’t stop moving the data.</li>
+</ol>
+</li>
+</ol>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-initial-optimizations"><strong>Initial Optimizations</strong></h2>
+
+
+<p><br>Since we had the objective to increase the throughput to balance DataNodes at a greater speed to balance them faster, we optimized our HDFS balancers with the existing DataNode properties to increase the throughput.<br>Although we increased the speed of the balancer up to 3x, the throughput still wasn’t sufficient. We had too many highly occupied nodes and the number of DataNode pairs to which the data would be transferred in the existing algorithm would be significantly less. Also, we couldn’t improve the throughput from each node through balancer threads, as increasing it would increase the slowness of the node and affect read/write traffic. Thus, we needed to increase the number of DataNode pairs, which would ultimately lead to an increase in balancing throughput.<br><br>DataNode and Balancer Configs that we used are mentioned below. Configurations for your workloads may be different based on your situation. </p>
+
+
+<p><strong>DataNode configuration properties:</strong></p>
+
+
+<figure class="wp-block-table has-small-font-size"><table><tbody><tr><td><strong>Property</strong></td><td><strong>Default</strong></td><td><strong>Fast Mode</strong></td></tr><tr><td>dfs.DataNode.balance.max.concurrent.moves</td><td>5</td><td>250</td></tr><tr><td>dfs.DataNode.balance.bandwidthPerSec</td><td>1048576 (1MB)</td><td>1073741824 (1GB)</td></tr></tbody></table></figure>
+
+
+<p><strong>Balancer configuration properties: </strong></p>
+
+
+<figure class="wp-block-table has-small-font-size"><table><tbody><tr><td><strong>Property</strong></td><td><strong>Default</strong></td><td><strong>Fast Mode</strong></td></tr><tr><td>dfs.DataNode.balance.max.concurrent.moves</td><td>5</td><td>250</td></tr><tr><td>dfs.balancer.moverThreads</td><td>1000</td><td>2000</td></tr><tr><td>dfs.balancer.max-size-to-move</td><td>10737418240 (10GB)</td><td>107374182400 (100GB)</td></tr><tr><td>dfs.balancer.getBlocks.min-block-size</td><td>10485760 (10MB)</td><td>104857600 (100MB)</td></tr></tbody></table></figure>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-algorithm-optimizations"><strong>Algorithm Optimizations</strong></h2>
+
+
+<h3 class="wp-block-heading" id="h-increasing-datanode-pairs-for-high-throughput">Increasing DataNode pairs for high throughput</h3>
+
+
+<p>More DataNode pairs meant that we could have more concurrent block transmission, hence a key improvement is to construct more pairs. Due to the existing algorithm, a highly skewed cluster formed fewer DataNode pairs.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="549" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-4-Balancer-Original-Algo-1024x549.jpeg" alt="" class="wp-image-1082506" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-4-Balancer-Original-Algo.jpeg 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-4-Balancer-Original-Algo.jpeg 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-4-Balancer-Original-Algo.jpeg 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-4-Balancer-Original-Algo.jpeg 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=1640,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-4-Balancer-Original-Algo.jpeg 1640w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 4: Existing Algorithm.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>In the existing algorithm for HDFS Balancer, DataNodes above a cluster’s average utilization (i.e., above-average utilized and over-utilized nodes) had much higher numbers compared to below-average utilized and under-utilized nodes. Thus, we faced the problem of scarcity of the nodes to move the data from highly utilized DataNodes, which resulted in highly utilized DataNodes not coming down speedily.<br></p>
+
+
+<p>In the above diagram, there are 8 DataNodes above average and 4 DataNodes below average utilization, which would lead to 4 targets where data could be moved.<br>The aim was to modify the HDFS algorithm such that more pairs are formed for DataNodes, thus leading to more throughput from high-usage DataNodes, resulting in uniform utilization as well as a speedy bump down of usage with more coverage of DataNodes.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Our idea was to use a percentile-based algorithm for creating more DataNode pairs.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/HlfZlWPK_wVdej0xQY_1gYkFAWt7JpDbSyPnbE4eLyQaV9-jk_XFbgFszAVnxWfTzTvMg_6MhjL3lsrAImSeStQrrcXNiIdM_W2zNWEHJlWnCsxhme1CD07Ju4Q8QoPHgBzqg-GDgSmcBSu7A8yh9RQ" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 5: New Algorithm.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>In the new algorithm, we created an adjusted average based on percentile, which would increase the number of nodes to which the data could be moved. Above average/over-utilized DataNodes would try to come near to overall cluster utilization, whereas under-utilized/below average utilized nodes would try to come near adjusted average of percentile. With a percentile-based algorithm, we would aim to bring our adjusted average near overall cluster utilization.</p>
+
+
+<p>We would use a percentile-based algorithm to increase the DataNode pairs. In the highly skewed cluster, the percentile was quite high. Taking an example of the above diagram, we took percentile as P60, our adjusted average is now 86.7%. In this case, the count of over-utilized/above-average utilized nodes decreases, and under-utilized/under-average utilized nodes increase.</p>
+
+
+<p>Now, there would be 5 over-utilized and above-average utilized nodes and 7 under-utilized and under-average nodes, which will lead to the formation of 7 pairs max from 4 pairs.</p>
+
+
+<p>We had a new Hadoop configuration property, <em>dfs.balancer.separate-percentile</em>,</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/ouUojzw_My_1YuqQvm4oGFoXtN03qy9mBcdjsfcPCHi7thgD_wkYfo3lkzZN6AzFvG2rs2qDHuftg2D3D8vpFw03dk94_r_UhuSUvSfkUr7w2YGuCOP1tNO3QDEE9RV8LwCkjScxreh3_YXyC0vPkPc" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 6: New Hadoop Configuration for Defining Percentile.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>which was by default 0.5, denoting the 50th percentile. If we deployed the balancer command with -dynamicBalancer, this percentile algorithm would take effect and the adjusted average would come into the picture with more throughput.</p>
+
+
+<p>We could also use this threshold to balance dynamically. For example, if DataNodes would go above 90%, we would balance them aggressively (i.e., with increased speed). Thus, we would balance the top 20% of DataNodes, which would lead to concentrating moverThreads on the top 20% of highly utilized sources, and data would move faster from highly utilized DataNodes and bring usage down faster.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="417" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-7-Aggressive-balancer-code-1024x417.png" alt="" class="wp-image-1082510" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-7-Aggressive-balancer-code.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-7-Aggressive-balancer-code.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-7-Aggressive-balancer-code.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-7-Aggressive-balancer-code.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=1988,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-7-Aggressive-balancer-code.png 1988w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 7: New Hadoop Configuration for Defining Aggressive Balancing.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-moving-data-to-lower-occupied-datanodes">Moving data to lower occupied DataNodes</h3>
+
+
+<p>Due to automation (i.e., automatic removal of data from DataNodes to other DataNodes to send it for maintenance), frequent decommission happened to DataNodes in a large cluster, in which data from a decommissioned node was moved to other nodes, increasing the occupied percentage on those nodes. The new nodes that came up got slowly balanced, as they were not given priority.<br>Also, for example, if average utilization was 83% with a threshold as 3% and the DataNode of 90% moved some part of its data to a 79% node which becomes 81%. Now if the new client dumped data at 81%, it became 87%, which may require further balancing of this node, thus distributing the dispatcher and mover threads. </p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/lAap83ZaUUmXXZdZ45R2B9TuHzz3O8zzrYpaZpti5Srpdxga1oV2Ay6yBqrlLqRRfVYe5r0jiEYlyQe8EBhD_W9T5Z_QsbkvToqR1-VPXv-9grrMlFCNb61rpOZtsv4jG1EX4Q3loB-vg-C0236qxdc" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 8: Old Algorithm – Pairs Formed.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/xoqmBEJU1prJmh7xmVNllTySnh2KfypKUZXcfY2Kp4qG3XMWEVnNMkpOQjm9EwfarrVBwn4IlD5gnaScUKbt7jRDQnBziP4EcDQTxEErbfKzT-5xu7nzj8EpOjDxKS1aFImRaPN_U5Iz2EEKSpjJp8Q" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 9: Old Algorithm – New Over-Utilized Nodes Came Up.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/qmXk_2q380kv8Nmo5YBY-jL_T6o88ZDB9sZ_M2RG8FCQ_Cs8vCKV5YiP11ahdV98lhsqvkhhb1yxJwVHySa__dVbeW0EtUlS96qwxHwl0eGYnVAnc6kf7vnx-KZCXEtKxG0muax_12jqY5aYP0cZtgE" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 10: New Algorithm – Preferred Optimization.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Our enhancement was to prioritize smaller occupied DataNodes by sorting in ascending order nodes in under-utilized nodes or below-average nodes, to balance the data first from over-utilized nodes, then above-average utilized nodes sorted in descending order, so that the nodes in between do not come into the picture, when balancing to prevent recursive balancing.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-better-observability"><strong>Better Observability</strong></h2>
+
+
+<p>We didn’t have a metric on DataNode pairs that are formed between over-utilized and underutilized, overutilized and below-average utilized and underutilized and above average utilized between the same node group, same rack, and any other rack and other relevant metrics. Hence, we weren’t able to calibrate the traffic distribution between these pairs. In order to find out where the DataNode pairs could be increased to increase the throughput, we created a new dashboard.</p>
+
+
+<p>In the end, we added more than 10 metrics to track the performance of our change in algorithm, which would help us calibrate custom algorithms for the balancer more.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter is-resized"><img decoding="async" src="https://lh7-us.googleusercontent.com/qymsO6tHpnV1x5Re2lVFYtX5UqTArgNP0PT7JTLi2aua8DL9-GTRTMbFQZ7fF-WccCBJvmv5zXP72Akx1ejdFgBH2YdtFa_4tgz1CHFWyonX74vzT8OpAjRaGqDTUdNFWPAYgnGiJXaq7bg_7UtwbEw" alt="" style="aspect-ratio:1.7758046614872365;width:700px;height:auto" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 11: Snapshots of our Metrics Dashboard.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-results"><strong>Results</strong></h2>
+
+
+<p>With optimizations in the balancing algorithm, we increased the throughput by more than 5x, with no DataNodes with higher utilization than 90%, as well as brought down the usage of the DataNodes overall. Also, there is now no need to deploy a manual balancer that took only certain hardcoded nodes to balance the data, as our optimization in the algorithm took care of that.</p>
+
+
+<p>As part of our new algorithm – </p>
+
+
+<ul><li>Increased throughput – We increased the throughput by more than 5x.</li>
+
+
+<li>Bringing down highly used datanodes – We brought down DataNodes above 90% utilization to 0.</li>
+
+
+<li>DataNodes around same utilization – Reduce overall usage of datanodes and bring them around the same capacity. We had all the DataNodes below 85% utilization for our biggest cluster.</li>
+
+
+<li>Manage the capacity better – Our cluster utilization increased from 65-66% to around 85% for HDFS clusters, with us having capacity bottlenecks. We now had no highly occupied datanode even though the cluster utilization was higher than ever.</li>
+</ul>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/xLa6b1OocD2j8moRGaxLJL_qbjP_xD412Zib_vZv3uYV-tXefy1Vq8IZK4Y1k8F-B_lWdetYp4_-xunCBgCdB3Ov0hhpnuKlLVARGodpE6nUURsocv7menNOQKubFT5oiBwCM7yyYfsmw4R1P64UMZ4" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 12: DataNodes at a similar level due to the algorithm change and below 85% utilization for our biggest cluster.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter is-resized"><img decoding="async" src="https://lh7-us.googleusercontent.com/eO5trlhcsa5iPseVoe0deceN0afiwUstj3oyk95aGYV4xV6vO9ap3juytv9bnLQMitL88-tnRmKblbiVzmE6Li9vmAG0aRWXQ_Y5rIzo8Z846ZFOtm6BMoaFwHcQzIw8BZVgW4n2-1OTRolCH9LSnRE" alt="" style="aspect-ratio:1.7621145374449338;width:700px;height:auto" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 13: Panels reflecting the DataNode skew is reduced.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/uqyVOYZWIMQ33KfRVuA4LeLDiASqtaMThAef2CjJ8Qa2_mNvgi51nJcH2A1VmhML8yXyE7e_cHmD8_5-zgS2OUe6PqOaEZQBbfNYvo_npxkCxKaKisWB_ZRWyOQQiN8Ox8uomG_T6DGJjR4dRPVU7Lc" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 14: Before balancer algorithm changes – Datanodes with high usage above 90% are 50.8%.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/8jioc04QB8VJcyCm7bKU-IEx6cbiTgLeBe9O0aRb9CR4nwU8o4IRzQScNFOjhSns5XDspdY-u3cK5iirYw7QH9dwrCNoFoUfstbTMRuciCWxR6CHZXFTDtT_p-wuCHVYko3wmssd4f2PJnUXPa6HbPU" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 15: After balancer algorithm changes – Datanodes with high usage above 90% are below 0.</figcaption></figure>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" width="844" height="662" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-16-Cluster-previous-capacity.png" alt="" class="wp-image-1082512" style="aspect-ratio:1.2749244712990937;width:700px;height:auto" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=844,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-16-Cluster-previous-capacity.png 844w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-16-Cluster-previous-capacity.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/03/Figure-16-Cluster-previous-capacity.png 768w" sizes="(max-width: 844px) 100vw, 844px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption"> Figure 16: One of our clusters with less cluster utilization around 65%.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter is-resized"><img decoding="async" src="https://lh7-us.googleusercontent.com/FUzDUIGryAJWwVwckoZQPUKatRhcPpBWOxQrGHXh9P8-y3mOTVcgJEnJJjCHromXrwQtbz1T_7t7V7TEtQ9lNT9XI4IabGVADQ2rIzXK3FeDb4Zpd93h4i0a_3Y0oDCGRdxiNx6iGwomsnTU4tqmgBM" alt="" style="aspect-ratio:1.334375;width:700px;height:auto" referrerpolicy="no-referrer"><figcaption class="wp-element-caption"> Figure 17: Cluster utilization increased to around 83% for the same cluster above.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/4xMTrAtGQ4KGaHED3rgIgLPSWn3YMy25QcXsCD4uhPn3YT8M9_PiyKp7NVwdqqJexncQPxAdWg7EFk_jIQR8nYO0hPn-IAU7QA2ho2syCDMroCNi7jSpnCDXDSuYOCQgf3EcoTwV4vT-Spp1WraoKkk" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 18: Increase in throughput by more than 3x due to algorithm changes.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-conclusion"><strong>Conclusion</strong></h1>
+
+
+<p>In an HDFS cluster, data could get skewed among different DataNodes and could lead to high I/O on the node, leading to it being slow or going down, causing data loss. The new algorithm would help in balancing the DataNodes faster to achieve greater efficiency, service reliability, and high performance while preventing a higher probability of slowness, higher risk of node failure, and data loss. </p>
+
+
+<p>In Uber, we deployed this change to multiple clusters to increase the balancing throughput. We are raising an open-source patch for our optimizations. Uber HDFS team continues to work on solving similar data distribution problems – given our scale, even a small improvement can result in a huge gain. </p>
+
+
+<p>[1] Uber keeps data with different access temperatures to dedicate clusters for better reliability and cost efficiency. We apply the warm tiering to move data from hot cluster to warm cluster and adopt EC conversion to move data to cluster with erasure coding feature, which saves 50% capacity. </p>
+
+
+<p class="has-small-font-size"><em>“Apache®, Apache Hadoop®, and Hadoop®, are either registered trademarks or trademarks of the Apache Software Foundation in the United States and/or other countries. No endorsement by The Apache Software Foundation is implied by the use of these marks.”</em></p>
+https://www.uber.com/blog/balancing-hdfs-datanodes-in-the-uber-datalake/https://www.uber.com/blog/balancing-hdfs-datanodes-in-the-uber-datalake/Thu, 14 Mar 2024 05:30:00 GMTUberEngineeringData / MLLoad Balancing: Handling Heterogeneous Hardware<h1 class="wp-block-heading" id="h-overview"><strong>Overview</strong></h1>
+
+
+<p>This blog post describes Uber’s journey towards utilizing hardware efficiently via better load balancing. The work described here lasted over a year, involved engineers across multiple teams, and delivered significant efficiency savings. The article covers the technical solutions and our discovery process to get to them–in many ways, the journey was harder than the destination.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-background"><strong>Background</strong></h2>
+
+
+<p><a href="https://www.uber.com/blog/better-load-balancing-real-time-dynamic-subsetting/" target="_blank" rel="noreferrer noopener">Better Load Balancing: Real-Time Dynamic Subsetting | Uber Blog</a> was a related blog post that predates the work described here. We won’t repeat the background–we recommend skimming through the overview of our service mesh there. We’ll also be reusing the same dictionary. This post focuses on the workloads communicating via the service mesh explained above. This covers the vast majority of our stateless workloads.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-problem-statement"><strong>Problem statement</strong></h2>
+
+
+<p>In 2020, we started work to improve the overall efficiency of Uber’s multi-tenant platform. In particular, we focused on reducing the capacity required to run our stateless services. In this blog post, we’ll cover how individual teams making rational decisions led to inefficient resource usage, how we analyzed the problem and different approaches, and how, by improving load distribution, we got teams to safely increase CPU utilization and drive down costs. The post focuses on CPU only, since this was our primary constraint.</p>
+
+
+<p>First, some context: at Uber, most capacity decisions are decentralized. While our platform teams provide recommended targets and tools like auto-scalers, the ultimate decision to adopt specific targets lies in each of the product teams/organizations. A budgeting process exists to curb unlimited allocations.</p>
+
+
+<p>As part of the budgeting process, we noticed what we thought were unreasonably low utilization levels. However, attempts to increase the utilization were met with concerns from the product teams–they were rightly worried that increasing the utilization would risk the system’s reliability and affect their availability/latency goals.</p>
+
+
+<p>The cause of the problem was presumed to be suboptimal network load balancing. Many workloads had tasks with CPU usage higher than average. Those outliers worked fine during normal operations, but struggled during failovers–and the desire not to break the SLAs pushed our average utilization downwards.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/VPz0oGg-6KU9AQlKl7p6jeMb71w1ExYry6MeA5yDkQD_XQb62eP9S48IH_ZfGItt4tzYYz6TlzmYYaShRNRFe2x01S75ACNiS_T-OjaLcGO6FyfmyJF21eH0ks9v1fxPzvkBA-3cl0CGBKT3bY8oP-E" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 1: A typical “imbalance graph.” Each line represents the CPU usage of a container.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/gV0L88878EKTUFagchXUUUkaTB0AieIEAzm4DDNKfjaATpUjMR_0yFE8vK-OY5w37lFhRS6DIRFZxEa-LE_pGYsk2PU4wQdEOfanI9pXjzqnAClzepSHXlA78fUwifiXWWF7QWlhc4Bo9WWf4g8-yfk" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 2: A less obvious case: container utilizations are distributed across a band, but some are utilized more than others.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-asymmetry-of-impact"><strong>Asymmetry of impact </strong></h3>
+
+
+<p>An important aspect of load imbalance is the <strong>asymmetry of its impact</strong>. Imagine a scenario where out of 100 workloads, 5 are under-utilized. This impacts efficiency, but the cost is relatively low–we’re not using 5% of our machines as efficiently as possible. </p>
+
+
+<p>If the situation is reversed and the same 5 workloads are <em>over</em>-utilized, the situation is much more severe. We are likely affecting customer experience and potentially affecting the system’s reliability. The easy solution to avoid these hotspots is to reduce the average utilization of the whole cluster. This will now have a <em>much</em> more significant impact: <strong>95% of the workloads are underutilized</strong>, meaning a much more significant waste of (financial) resources.</p>
+
+
+<h3 class="wp-block-heading" id="h-the-forest-and-the-trees"><strong>The forest and the trees</strong></h3>
+
+
+<p>Since the outliers were easy to spot, we initially focused on fixing and chasing them one by one, trying to root-cause and fix each issue individually as soon as possible. The results of these individual fixes weren’t always as expected. Some of our changes had a lower impact than expected or only impacted a subset of the system. Similarly, other changes later on resulted in unexpectedly significant improvements. This was due to several independent issues being at play. This “forest of issues” resulted in the work being largely sequential–we would only find a new, more minor issue once its larger sibling was fixed.</p>
+
+
+<p>In retrospect, the “surprise” part could have been mitigated with more analytical rigor–we could have understood the system more and collected more samples upfront. The sequentiality of the work would likely have been the same, though–it’s only through the process we learned how to understand and measure the system.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-measuring-the-impact"><strong>Measuring the impact</strong></h2>
+
+
+<p>Perhaps surprisingly, one of the most disputed aspects of the project, until the very end, was measuring the impact. The discussions involved folks from different teams and organizations joining and leaving the project at different times. Each involved party had a valuable, but slightly different perspective on the problem, its priority, and potential fixes.</p>
+
+
+<p>Just measuring the impact consistently was surprisingly complicated. Clearly, we should measure the outliers–we quickly settled on using the CPU utilization of the p99th most utilized task of a given workload. After some discussions, we agreed to use the average as the base, leaving us with p99/average as the <em>imbalance indicator</em>. </p>
+
+
+<p>However, even that was surprisingly vague:</p>
+
+
+<ul><li>A workload runs in multiple clusters across multiple zones. Should the p99/average be calculated across all its instances or for each cluster individually? If it’s per cluster, how do we weigh the results? This decision <em>dramatically </em>affects the final numbers.</li>
+
+
+<li>Workloads run in multiple regions, yet unlike zones, our regions exhibit strong isolation–where to send traffic is outside of networking control. Thus, the networking team might care about a different indicator than the business.</li>
+
+
+<li>A typical workload has a periodic pattern–a service might be most busy on a particular day of the week and underutilized at other times. Should we measure the imbalance at the peak only or throughout the day? If at peak, how long of a time frame should be considered peak? Do we only care about the single weekly peak?</li>
+
+
+<li>Our workloads typically run in an active-active pattern, with each region having some spare capacity for a potential failover. The load imbalance matters most during those failovers–should we try to measure it only then? If so, the frequency of our measurements will be reduced–typically, we would get a simple sample per week.</li>
+
+
+<li>The workloads are noisy. A service rollout typically results in an imbalance spike (as new containers come and warm up). Some workloads might be quick to roll out (per increment) but roll out tens of times per day via a CD pipeline. Other workloads are much slower, and a single rollout can take hours. Both types of rollouts can overlap with peak times. On top of that, there are “atypical events” like temporary performance regressions, traffic drains, load tests, or incident-related issues.</li>
+
+
+<li>Most workloads follow a “standard” pattern, but some (more critical) services have been partitioned into custom shards with separate routing configurations. Similarly, a small subset of essential workloads is additionally accessible by custom peer-to-peer routing. Finally, another small subset of services runs on dedicated hosts. These dimensions might affect our tracking.</li>
+</ul>
+
+
+<p>Once we settle on the per-workload indicator, the problem expands to multi-service:</p>
+
+
+<ul><li>How do we weigh the individual workloads in the final score? </li>
+
+
+<li>How do tiers (priority) of each service affect their weight in the final score?</li>
+
+
+<li>Does the fact that different workloads have different periodical patterns affect the score? Workloads typically have weekly and daily peaks, but those peaks are not simultaneous.</li>
+
+
+<li>Can we decompose the final indicator into sub-components to track the imbalance of individual zones or clusters?</li>
+</ul>
+
+
+<p>The indicators must be available in real time for development and monitoring–here, we care about the highest precision possible, typically sub-minute. However, the same indicator must be available over long periods (years), where we need to roll the data up into day-sized chunks while keeping all the previous weighting considerations in mind.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-actual-numbers"><strong>Actual numbers:</strong></h2>
+
+
+<p>Ultimately, we created a “Continuous imbalance Indicator.” For each workload, for each minute, we calculated the p99 (say, 5 cores) and average (say, 4 cores) CPU utilization. That, combined with the number of containers, allowed us to calculate “wasted cores.” For the example above, 10 containers would result in 10*4=40 (cores) <em>usage, </em>(5-4)*10=10 <em>wastage </em>cores, and the resulting indicator of 1+10/40=1.25. This mapped intuitively to the “standard” p99/average calculation of 125% that humans could do when debugging live.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/ZyU1H3XwK_fGjpDhsyhcKROE_XnjnbhmTKc_AkW1b-yvzLpTJ4TbnDiAqQ_b5jcOhM-4RFnaqrjVTFUHfNVqCRgh_299GXdMaUQeRX5Ca8eGP8mO8WrGDaHoo77l1OL5uOJJjHnNCFIqUEh3EgnzauY" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 3: theoretical definition of imbalance.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>When done over time, this effectively became a ratio of areas under two curves: p99 and average utilization.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/Ed94kW9bEsKmlR9f6liB9hLJFJTRA2eWNbC61KrTCvqjRR16FF_17rG_29z2qqzrzobImlGT0S-GrF0ISBBjWaXnEV2TGRwIMFr_8R3E4lM5D1exq-LUcqAw4YjIVVjoVFbRYXowXbpESs_2zLlcIUM" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 4: Continuous Imbalance Indicator on a real-time dashboard.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>The benefit of this approach was that since the wastage and utilization were calculated in absolute numbers of cores, it allowed us to aggregate them in custom, arbitrary dimensions: per service, per service-per-cluster, per group of services, per cluster, per zone. Similarly, any time window (hour, day, week) naturally worked–it was as simple as summing up a range of integers. Additionally, the indicator naturally gives higher weight to “busy” periods–imbalance at the peak is more critical than imbalance off-peak. The downside was the difficulty of explaining the indicator to humans, but we found that the approximation as a “weighted p99/average” is acceptable.</p>
+
+
+<p>An alternative approach of calculating a ratio of “weekly p99 of p99s” and “weekly average of averages” was easier to explain on an individual service basis but suffered from high sensitivity to random events (drains, failovers, load-tests, deployments), which made it noisy. Additionally, the cross-service weighting was less straightforward.</p>
+
+
+<p>The above metrics were made available in real-time metrics in Grafana and long-term storage in Hive. We needed to write custom pipelines to pre-process the indicator daily for visualization.</p>
+
+
+<h3 class="wp-block-heading" id="h-different-slicing"><strong>Different slicing</strong></h3>
+
+
+<p>A particular wrinkle about measuring load imbalance is worth calling out: how you slice your data dramatically affects the results. It is tempting to start with small slices (clusters, zones, regions) and then “average” the imbalance. Sadly, this doesn’t work in practice. For example, it’s possible to have two clusters with (averaged) p99/average ratio of 110%, but when looking across the whole workload, the imbalance might be much higher–up 140% in our cases. Similarly, combining two clusters of higher imbalances might result in a lower imbalance.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-addressing-the-issues"><strong>Addressing the issues</strong></h1>
+
+
+<h2 class="wp-block-heading" id="h-the-first-step-getting-hacky-data-first"><strong>The first step: getting (hacky) data first</strong></h2>
+
+
+<p>We started by building Grafana dashboards for real-time observability. This allowed us to measure impact individually per service in real time but didn’t help in understanding the root cause. While the assumption was that the load balancing was at fault, we didn’t *really* know. The initial problem was the lack of observability, where we faced two issues.</p>
+
+
+<p>First, due to cardinality issues, our load balancers did not emit stats by each backend instance. With many services running thousands of containers and hundreds of procedures, this would have caused both a memory usage explosion in our proxy and made the stats not-query-able for even the medium-sized services. Luckily, an intern project that summer added an ability to emit stats on an opt-in basis (saving the proxy memory usage) on a new metrics namespace (leaving the existing stats intact). Together with <a href="https://chronosphere.io/learn/how-can-recording-and-roll-up-rules-help-your-metrics/" target="_blank" rel="noreferrer noopener">roll-up rules</a>, we could now introspect most services (as long as we only enabled the extra visibility for a few of them at a time).</p>
+
+
+<p>Second, we had lost the ability to uniquely identify instances across our compute and networking stacks. At the time, we could see the CPU usage of each target but couldn’t easily map it to a container. The available “unique identifier” of a <em>host:port</em> would have broken our metrics (again, <a href="https://chronosphere.io/learn/what-is-high-cardinality/" target="_blank" rel="noreferrer noopener">cardinality</a>) due to our wide IP target range and dynamic port usage. The discussion of a proper solution had previously stalled for quarters. Ultimately, the networking stack implemented a short-term solution based on sorting IP addresses and emitting integer-based instance IDs. These were not stable across deployments, but together with some more hacky scripting, allowed us to get the data we needed.</p>
+
+
+<p>This step provided important lessons:</p>
+
+
+<ul><li>Always get the data first</li>
+
+
+<li>Well-placed, targeted, isolated hacks can be extremely useful</li>
+
+
+<li>You don’t need perfect observability to draw the correct conclusions</li>
+</ul>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-manual-analysis"><strong>Manual analysis</strong></h2>
+
+
+<p>Once we had in-depth visibility into the issue, we hand-picked a few large services and tried to analyze the root causes. Surprisingly, the load balancing was not at fault–at a 1-minute window (our CPU stats resolution at the time), the RPS distribution was almost perfect. Each container was receiving an almost equal number of requests, with a difference below 0.1% for most applications. Yet, within the same window, the CPU utilization varied greatly.</p>
+
+
+<p>After several weeks of investigations, we were able to quantify several independent reasons:</p>
+
+
+<ul><li>Some significant sources of traffic forced imbalance. For example, many of our systems are “city aware,” with a city always being in a single region. This naturally drove different amounts of traffic to each region, with proportions changing continuously as cities woke up and fell asleep.</li>
+
+
+<li>Services ran across several hardware SKUs, both within and across clusters. </li>
+
+
+<li>Even the theoretically identical hardware showed significant performance differences.</li>
+</ul>
+
+
+<p>Some of the imbalance was left in an “unknown” bucket. The majority of it turned out to be issues with our observability. We currently attribute the remainder (less than 20% of the original imbalance) to <a href="https://en.wikipedia.org/wiki/Cloud_computing_issues#Performance_interference_and_noisy_neighbors" target="_blank" rel="noreferrer noopener">noisy neighbors</a>.</p>
+
+
+<p>The graph below shows the initial analysis for one of our biggest services from 2020.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/IovK_kUSNl_76Da7EKegaYqylzW4OiEV2s09RUzrt8Ow18SAqVzjyVT2Wrj3HNseZCmCS_J1WN-NQ0tNJAbVO5OvknwSFOnFDpAmldb5QDSGtTrFedRGz9OBgOnX2aMe1ymxQui-d4sEXFATK81vruM" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 5: Imbalance understood.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-forced-to-build-long-term-aggregations"><strong>Forced to build long-term aggregations</strong></h2>
+
+
+<p>At that point, we wanted to start with any low-hanging fruit. The <a href="https://www.uber.com/blog/better-load-balancing-real-time-dynamic-subsetting/" target="_blank" rel="noreferrer noopener">Better Load Balancing: Real-Time Dynamic Subsetting | Uber Blog</a> gave us a few knobs we could tweak. This, however, instead of being easy, presented a new problem.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/AHpjR9Jv7KdKJ-xuaOkLWwL9iswUHo2Of3qYZlMnURcDdhlawPN6XfL9pf96j3rFVjclApy_BT1IOEfX1w7HHzVBiuljPda6NKXGWgzQ839BfeZw53O1AYa-hYsk0qgq-2cAIEIF5RcnyaKf5ETUuSo" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 6: Patterns in weekly CPU utilization of a single service.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Our services exhibit heavy daily and weekly cycles (see above). On top of that, we frequently see spikes caused by failures, deployments, failovers, or ad hoc events. After rolling out a change, only a massive improvement (20%+) would be human-spottable, but our changes were too subtle.</p>
+
+
+<p>This resulted in the observability decisions explained in the previous paragraphs. We built pipelines to aggregate data over long periods based on a stable and spike-resilient metric. On top of that, we could slice the metrics by clusters, zones, regions, or groups of services–this, in turn, lets us investigate more “suspicious” behavior.</p>
+
+
+<p>Some pre-existing knobs let us reduce the service-mesh-induced part of the load imbalance, but it was a small fraction of the overall problem.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-possible-solutions"><strong>Possible solutions</strong></h2>
+
+
+<p>An obvious first step was to look at low-level hardware configuration and OS settings. A few separate threads were started to look at these.</p>
+
+
+<p>Solving the hardware heterogeneity required a more complicated process. Many approaches were possible, from:</p>
+
+
+<ul><li>Modifying <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/resource_management_guide/sec-cpu" target="_blank" rel="noreferrer noopener">CFS parameters</a> to make every host in the fleet appear the same despite the underlying hardware being different.<ul><li>This option was attractive but eventually dismissed due to unclear impact on various software stacks (like <a href="https://pkg.go.dev/runtime#GOMAXPROCS" target="_blank" rel="noreferrer noopener">GOMAXPROCS</a>). In retrospect, this also prevented us from configuration utilizing <a href="https://www.uber.com/blog/avoiding-cpu-throttling-in-a-containerized-environment/" target="_blank" rel="noreferrer noopener">cpu-sets.</a> </li>
+</ul>
+</li>
+
+
+<li>Modifying host-to-cluster placement to achieve uniform clusters.</li>
+
+
+<li>Modifying the per-service cluster placement to guarantee stable, but not uniform, host selection.</li>
+
+
+<li>Moving to cloud-style host management, where each team would select a particular type of hardware.</li>
+
+
+<li>Many possible service mesh changes to achieve better load <em>im</em>balancing.</li>
+</ul>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/YC4s0sGZby4epTYOC36Um_cXU12K4MNkNHr_RSpt31Nijf4xB2IrGiPs3TJosQOVCrfsNnNov_ym5o2A9SLApgHEQl3u3Uu_JpuEHsh4w2gHuytW0lxB09_iU0oOdzf0p_6tpnAq7muT8DtwhUhcBcw" alt="Screenshot of a spreadsheet, fields colored by the feasibility" title="Possible fixes (unreadable on purpose)" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 7: Option matrix (blurred out on purpose)</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Out of the possible options, changes to the service mesh were chosen for several reasons. Technically, changes on our layer required no changes to the physical layout of the data centers and no per-service migrations. Tactically, we could also deliver the changes quickly to most services.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-changes"><strong>Changes</strong></h1>
+
+
+<h2 class="wp-block-heading" id="h-hardware"><strong>Hardware</strong></h2>
+
+
+<p>While root-causing variance within hardware SKUs we found many issues with hardware, firmware, and low-level software. They ranged across OS settings, CPU governor settings, firmware versions, driver versions, CPU microcode versions, or even kernel version incompatibility with Intel HWP. A general root cause of this was that, historically, once the hardware was ingested and turned up in the fleet, it was left untouched unless it had issues. Over time, though, that led to a drift between machines. </p>
+
+
+<p>Uber runs in a mixed cloud/private setup, so we naturally experienced cloud-specific issues as well. Like other companies, we’ve seen multiple cases of theoretically identically provisioned VMs not performing similarly (<a href="https://www.reddit.com/r/aws/comments/547xbx/netflix_found_5x_performance_variation_between/" target="_blank" rel="noreferrer noopener">this</a> is still real). Similarly, we’ve seen cases where workloads running fine on-prem triggered issues on the cloud. To make it worse, the cloud meant less visibility into the details of the underlying infrastructure.</p>
+
+
+<p>Fixing all these would be nearly impossible without a recently finished <a href="https://www.uber.com/en-IN/blog/crane-ubers-next-gen-infrastructure-stack/" target="_blank" rel="noreferrer noopener">Crane project</a>–we could measure, fix, and roll out changes to tens of thousands of machines without human involvement. All of the issues discovered are now detected and remediated automatically.</p>
+
+
+<p>A clear benefit of these fixes was that they applied to every workload, no matter how it processed or originated its work (Kafka, Cadence, RPCs, timers, batch jobs, etc.). They were also giving us effectively free capacity, on top of the load imbalance improvements–some CPUs “became faster” overnight.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-observability"><strong>Observability</strong></h2>
+
+
+<p>Observability was an interesting part of the problem. Before the project started, we knew we had limitations in the sample collections due to 1-minute window sizes, but we found more issues.</p>
+
+
+<p>Technically, the problems were caused by interactions between <a href="https://en.wikipedia.org/wiki/Cgroups" target="_blank" rel="noreferrer noopener">cgroups,</a> <a href="https://github.com/google/cadvisor" target="_blank" rel="noreferrer noopener">cexporter</a>, our internal <a href="https://prometheus.io/" target="_blank" rel="noreferrer noopener">Prometheus</a> metric scraper, and <a href="https://github.com/m3db/m3" target="_blank" rel="noreferrer noopener">m3</a>. In particular, due to the metrics being emitted as ever-increasing gauges, any delays in stats collection anywhere in the pipeline would result in (large) artificial spikes in percentile calculations. A lot of work was put into preserving the timestamps of the samples as well as gracefully handling both target and collector services restarts. An example <a href="https://github.com/google/cadvisor/issues/2913" target="_blank" rel="noreferrer noopener">issue</a> was effectively breaking data collection for any large enough service.</p>
+
+
+<p>A fascinating aspect of the observability issues was related to human interactions – or the fact that humans cannot be trusted. Early in the project, we asked service owners what level of container utilization resulted in user impact (increased latencies). Interestingly, several months later, after we had rolled out the fix, when we asked again, we received the same answer. Both statements couldn’t be valid since we knew the old data was wrong. Ultimately, human irrationality resulted in net efficiency wins: service owners ended up running their services (effectively) hotter while thinking nothing had changed.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-load-balancing"><strong>Load balancing</strong></h1>
+
+
+<p>As explained in <a href="https://www.uber.com/blog/better-load-balancing-real-time-dynamic-subsetting/" target="_blank" rel="noreferrer noopener">Better Load Balancing: Real-Time Dynamic Subsetting | Uber Blog</a>, our service mesh works on two levels. Initially, the control plane sends over <em>assignments </em>deciding how much traffic should be sent to each target cluster. The imbalance between clusters is decided here.<br>Later, the data plane follows this assignment, but then it’s responsible for picking the right host–a second level of within-cluster load balancing is happening here. While we considered changing this model, we kept it unchanged and rolled out two solutions for each level.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-inter-cluster-imbalance"><strong>Inter-cluster imbalance</strong></h2>
+
+
+<p>At Uber, services run in multiple zones in multiple regions. Because each zone is turned up at a different time, there is no way to guarantee the hosts in each zone are the same–usually, the newer the zones, the newer the generation hardware they have. The difference in performance of zones leads to CPU imbalance.</p>
+
+
+<p>Our initial approach was to set a static weight for each zone; the weight will then be used in load balancing such that zones with faster hardware take more requests. The weight for each zone is calculated as the average of the Normalized Compute Unit (NCU) factor of each host deployed in that zone. The NCU factor measures host CPU/core performance based on a benchmark score, where the score depends on the product of core instructions-per-cycle (how much work is done by the core per clock cycle) and core frequency (how many clock cycles are available per second).</p>
+
+
+<p>We could then send more traffic to more powerful/faster zones, using static zone weights as a multiplier. </p>
+
+
+<p>Faster zones, with higher multipliers, will be routed with more traffic proportionally to increase CPU utilization, hence easing the CPU imbalance.</p>
+
+
+<p>For example, if a service has deployed 10 instances in zone A (weight = 1) and B (weight = 1.2), the load balancing will be done as if B has 12 (10 * 1.2) instances so that B will receive more requests than A.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/L22FN7eamJeUaNg5UhAokiSDGFniHnCMQqexYTjB-BIGI_bUVBreGefBUA1dqB3iOcbUUe6rVj9noQvx3Doqxjqigl7GkEk0aEYDYIOYmAVv9crDdtH6vwqrnQSwazMEU5nwjggUTjsRrhyDKWPqNkA" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 8: Zone Weights</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>This approach worked surprisingly well–we were able to mitigate the majority of the imbalance with relatively little effort. However, there were a few issues:</p>
+
+
+<ul><li>Zone weight is an estimated value (average NCU factor) across all hosts in a zone. However, a service could be extremely lucky/unlucky to be deployed on the fastest/slowest hosts in a zone.</li>
+
+
+<li>Though not frequently, the zones we operate on change due to turnup or turndown. Additionally, during turnup, we typically ingest hardware gradually, which might require multiple updates.</li>
+
+
+<li>Occasionally, we ingest new hardware into old zones to resize them or replace broken hardware. This hardware can be of a different type, resulting in a need to adjust the weights.</li>
+</ul>
+
+
+<h3 class="wp-block-heading" id="h-dynamic-host-aware-cluster-load-balancing"><strong>Dynamic Host-Aware Cluster Load Balancing</strong></h3>
+
+
+<p>Hence, we took a second look at the problem and invested in an advanced solution: Host-aware Traffic Load Balancing.</p>
+
+
+<p>This approach solves the drawbacks by looking at the exact hosts the service instances are deployed to, collecting their server types, and then updating the load balancing between clusters per service. This is achieved by making our discovery system aware of the mapping of a host (by IP), its host type, and weight such that for a given service deployed in a cluster, the discovery system could provide the extra <strong><em>weight</em></strong> info to our traffic control system. The diagram below shows an example:</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/BTH2IqexwVovC1iquHIIHhv744jyBweDXUPMKK4a5bDezGdqTbhfxk3SVVl5SZCz5bvZhFdg1td0ptbM1Hmy5SxzxxRBkDstE-jwYQzPSWQIPoukzhtztVliK1Gp6f3k6VUM6uSH5jLKGOsew_h7eH8" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 9: Dynamic Host-Aware Cluster Load Balancing</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>For service Foo, if we treat each instance equally, the load balancing ratio should be <strong>37.5</strong>%/<strong>62.5</strong>% instead of <strong><em>36</em></strong>%/<strong><em>64</em></strong>% shown in the example. The difference could become more significant if hosts are across multi-generations (we have up to 2X different weights between different hosts in our fleet).</p>
+
+
+<p>Compared with the static weight approach, the host-aware load balancing adjusts weight per service dynamically to reduce inter-cluster imbalance. It’s also much easier to maintain, as new host types are introduced infrequently.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-intra-cluster-imbalance"><strong>Intra-cluster imbalance</strong></h2>
+
+
+<p>The intra-cluster imbalance, as explained earlier, is the responsibility of the on-host proxy (called Muttley). Each proxy had complete control of selecting the right peer for each request. The original load-balancing algorithm for Muttley used by all services was least-pending, which would send requests to the peer with the smallest number of known outstanding requests. While this resulted in almost perfect balancing of RPS when measured in 1-minute intervals, it still resulted in an imbalance of CPU utilization due to different hardware types.</p>
+
+
+<h3 class="wp-block-heading" id="h-assisted-load-balancing-alb"><strong>Assisted Load Balancing (ALB)</strong></h3>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/_CL-GbcOXQlLQSs4Aq-a2Q7NaKUOA7HjoTu_P_nt0NnJM1biDm26uHcmmuVlePy5vgZenjeQsxii3KraWa3AU6ixB51OUDJehHqHMBQaM5co9vnXPy4AokvL1plsofFDmuqISUQ2drgx9sPcZylHFiQ" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 10: Assisted Load Balancing in a nutshell. </figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>We built a system where each backend <em>assists</em> the load balancer in selecting the next peer. An application middleware layer attaches load metadata as a header to each response. We effectively arrive at a coordinated system without central coordination. Where previously, each Muttley only knew about the load it caused (plus some information it could infer from the latencies), now, it learns about the total state of each backend dynamically. This state is affected not only by the backend itself (for example, running on slower hardware) but also by decisions made by other Muttleys. For example, if a backend is (randomly) selected into too many subsets, the system adjusts dynamically. This let us later on reduce the subset sizes for services on ALB.</p>
+
+
+<p>While a brief mention in the <a href="https://sre.google/sre-book/load-balancing-datacenter/#weighted-round-robin-eKspTGCm" target="_blank" rel="noreferrer noopener">Google SRE book</a> partially inspired this approach, we made a few different choices. Both changes were related to each other and were attempted to simplify the approach. We intended to start, evaluate, and move to a more complicated solution later–luckily, we didn’t have to. Late in the implementation, we discovered a<a href="https://netflixtechblog.com/netflix-edge-load-balancing-695308b5548c" target="_blank" rel="noreferrer noopener"> Netflix blog post</a>, and we had arrived at similar conclusions independently.</p>
+
+
+<p>Firstly, as the load metadata, we used the number of concurrent requests being processed, reported as an integer (q=1,q=2,..,q=100, etc). We considered reporting utilization, too, but that wasn’t immediately obvious (whether the reported utilization should be based on <a href="https://man7.org/linux/man-pages/man2/getrusage.2.html" target="_blank" rel="noreferrer noopener">getrusage</a> or <a href="https://en.wikipedia.org/wiki/Cgroups" target="_blank" rel="noreferrer noopener">cgroups).</a> Cgroups were more natural since that’s what service owners were using to track their targets. Still, they presented more challenges–our foundation team was concerned about the cost of each docker container scraping cgroups independently and potential tight coupling if the cgroups layout was to change, including during the cgroupsv2 migration. We could have solved this by integrating with a host demon collecting the stats, but we wanted to avoid adding a new runtime dependency. In the end, just using a logical integer worked well enough (with some tweaks, explained below). Additionally, it allowed per-service overrides without changing the load balancer code–while the vast majority of the applications use the standard load indicator, some (asynchronous) applications override it to reflect their load better.</p>
+
+
+<p>The second departure was the <a href="https://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf" target="_blank" rel="noreferrer noopener">power of two random choices</a> instead of the weighted round-robin. Since we had only a single integer as the load indicator, the pick-2 implementation seemed more straightforward and safer. Similarly to the above, this worked well enough that we didn’t need to change it. This approach turned out remarkably forgiving to failures across the whole range of our applications. Apart from typical crash looping or OOMing applications, we’ve had cases of bad/buggy implementations of the middleware not causing an incident. We speculate that since the weighted round-robin is more precise and “strict,” it would have likely performed “better” in some cases but could have resulted in <a href="https://en.wikipedia.org/wiki/Thundering_herd_problem" target="_blank" rel="noreferrer noopener">thundering-herd</a>-like scenarios.</p>
+
+
+<p>Implementation-wise, each Muttley uses a <a href="https://en.wikipedia.org/wiki/Moving_average#Modified_moving_average" target="_blank" rel="noreferrer noopener">modified moving average </a>to keep the score of each peer over 25 previous requests–this value worked best in our testing. To arrive at meaningful numbers for lower RPS cases, we scale up each reported load by a thousand.</p>
+
+
+<p>An interesting problem for the pick-2 load balancer is that the “most loaded” peer would <em>never </em>be selected. And because we discover peer load passively, we would also refresh its state, thus making it effectively unused until another peer gets even slower. We initially mitigated this by implementing a “loser penalty,” where every time a peer loses the selection, its “load value” is internally reduced–thus, with enough losses, the peer would be selected again. This didn’t turn out to work well for large-caller-instance-count-low-RPS scenarios, where sometimes it would take minutes for a peer to be reselected. Eventually, we changed this to a time decay where peers’ score is reduced based on the last selection time. We currently use a half-life of 5 seconds for score decay.</p>
+
+
+<p>We also implemented a feature we call internally a “throughput reward.” This stemmed from empirical observations that the newer hardware handles concurrent requests better. We noticed that when load balancing across two peers on diverse hardware and both peers report the same “load value,” we, as expected, send more requests to the faster peer. However, the faster peer’s CPU utilization (processed=15, CPU=10%, Q=5) will remain lower than the slower peer (processed=10, CPU=12%, Q=5). To compensate for this, every time a peer “finishes” a request, we reduce its load slightly to push even more requests to it. The faster the peer is relative to other peers in the subset, the more “throughput rewards” it receives. This feature reduced the P99 CPU utilization by 2%.</p>
+
+
+<p>A significant part (the majority) of the ALB design document was committed to the possible alternatives. We significantly considered, instead of attaching the load meta-data to each of the responses, using a central component to collect and distribute the data. The concern was that the metadata might consume a significant amount of available bandwidth. We internally have two systems that superficially seemed relevant. The first was the centralized health-checking system collecting health state from every container in the fleet in close to real time. The second was the real-time aggregation system described in the previous blog post.</p>
+
+
+<p><br>Re-using either turned out to be unfeasible: the health checker system could have easily collected the load status from all containers, but after collection, that system was designed to distribute the health changes infrequently–the vast majority of the time, the containers remained healthy. The load balancing indicators, however, change constantly and by design. Since we operate a flat mesh (every container can talk to every container), we would need to constantly distribute data about millions of containers to hundreds of thousands of machines or build a new aggregation and caching layer. The load-report aggregation system, similarly, was not a match–it was operating on aggregated per-cluster values at several orders of magnitude lower cardinality.</p>
+
+
+<p><br>Ultimately, we were happy with the chosen (response-header-based) approach. It was simple to implement and made the cost attribution easy – services pushing more RPS saw a higher bandwidth cost. In the absolute numbers, the cost of the extra metadata (~8 bytes per request) was almost invisible compared to the other tracing/auth metadata attached to each request.</p>
+
+
+<p>The latency was an interesting aspect of the “distributed” vs. “centralized” collection of the load data. Theoretically, the response header approach is close to real-time since the load is attached to each response. However, since each Muttley needs to discover this independently and then average the response over the previous responses, the discovery might take some time for low RPS-based scenarios. The health-check-based approach would require a full round trip (typically ~5s), but be distributed to all caller instances immediately.</p>
+
+
+<p><br>However, had we implemented it, we would have likely reduced the push frequency to something like 1 minute due to bandwidth concerns listed in the previous paragraph. This could have been enough to fix the hardware-induced skews but likely not other issues, like traffic spikes, slow-starting applications, or failovers. Both approaches could have likely worked slightly differently in different circumstances. Still, ultimately, we’re happy with the distributed approach–it’s easy to reason about and lacks centralized components that might fail.</p>
+
+
+<p>One downside of the chosen approach was that it requires cooperation from the target services. While minimal work is required, applying it to thousands of microservices would be arduous. Luckily, most applications built in the last few years at Uber used <a href="https://github.com/yarpc/yarpc-go" target="_blank" rel="noreferrer noopener">common frameworks</a> that allowed us to plug in the required middleware quickly. Several large services were not using the frameworks, but a concurrent multi-year effort had migrated almost all services. We found the decision to bet on the framework beneficial, as it had a compounding effect–service owners had one more reason to invest in migration. By the time we got to writing this post, virtually all services were on the common frameworks.</p>
+
+
+<h3 class="wp-block-heading" id="h-static-component-alb-v1-1"><strong>Static component – ALB v1.1</strong></h3>
+
+
+<p>The initial rollout did not meet our hardware-induced imbalance reduction goals. The primary reason was that our hardware runs heavily underutilized most of the time–we have buffers for regional failovers and weekly peeks. It turned out that with relatively low container utilization, the old hardware can burst high enough for latency differences not to be visible while consuming more CPU time. While this meant the load balancing was working much better under stress (when we needed it), it made product engineers uncomfortable with our target utilization–the imbalance looked too high off-peak.</p>
+
+
+<p>We added a second static component to the load balancing to address this. We utilized the fact that in our setup, the IP address of a host never changes. Since the proxy naturally knows the destination’s IP address, we only need to provide a mapping of the IP addresses to relative host performance. Because of the static nature of the data, we started adding this information as part of the build-time configuration. This weight in itself is not perfect: different applications perform differently on the same hardware type. However, combined with the ALB’s dynamic part, this worked well–we did not need to add application-specific weights.</p>
+
+
+<h3 class="wp-block-heading" id="h-testing"><strong>Testing</strong></h3>
+
+
+<p>A big problem during the development was testing. While we had a limited staging environment, the new solution needed to work with many parameters: some callers or callees had three instances, some three thousand. Some backends were serving <1, and some > 1,000 RPS. Some services served a single homogenous procedure, and others hundreds, with latencies varying from low milliseconds to tens of seconds. Ultimately, we used a dummy service in production with a set of fake load generators configured to represent a heterogeneous load. We ran over 300 simulations before finding the right parameters and attempting to roll out to production services.</p>
+
+
+<h3 class="wp-block-heading" id="h-results"><strong>Results</strong></h3>
+
+
+<p>We are happy with the final results–the exact numbers depend on the service and the hardware mix within each cluster. Still, on average, we reduced P99 CPU utilization by 12%, with some services seeing benefits of over 30%. The results were better the bigger the target service had per each backend–luckily, the largest services we cared about most were typically optimized enough. The same luck applied to onboarding–while Uber has over 4,000 microservices, onboarding the top 100 gave us the vast majority of potential reach.</p>
+
+
+<h3 class="wp-block-heading" id="h-rollout-and-future-changes"><strong>Rollout and future changes</strong></h3>
+
+
+<p>The rollout went well–we have not identified material bugs. The pick-2 load balancing and safe fallback were proven to be resilient. We onboarded services by tiers, region by region, trying to find representative types of services. </p>
+
+
+<p>ALB was rolled out to hundreds of our biggest services with minimal hiccups or changes:</p>
+
+
+<ul><li><em>Long-lived RPC Streams</em>. A small category of services was mixing up a small number of long-lived RPC streams with many very short-lived requests. We rolled back the onboarding there.</li>
+
+
+<li><em>Slow-starting Runtimes</em>. Around two years into the rollout, we tweaked the solution to handle slow-starting (Java) services better. These services could not serve the same request rate after startup due to JIT, but warm-up with recorded static requests was not working well enough; we needed to warm up the service with real requests at a lower rate. Here, we decided to seed each peer’s initial “weight” with a percentage of the average weight for the pool while leaving the algorithm’s core unchanged. We found this to work very well across a range of services, and we’re happy that this doesn’t require any static window settings, unlike Envoy’s <a href="https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/slow_start" target="_blank" rel="noreferrer noopener">slow start mode</a>–the algorithm adjusts to a range of RPS automatically.</li>
+
+
+<li><em>Data Prefetching on Startup.</em> Another very small category of services was pre-loading static data upon startup for several minutes. Due to the peculiarities of our service publishing mechanism, instances of those services are visible in our service discovery as “unhealthy.” The old algorithm strongly preferred the healthy instances. We changed that in ALB to avoid a thundering-herd-like scenario when a service cannot start after a temporary overload (due to each instance being instantly overloaded as they become healthy sequentially). The new algorithm significantly prefers healthy instances, but, in some cases, requests might be sent to “unhealthy” nodes. This doesn’t work for these services–while the reported error was <0.01% and 0.002%, we’re exploring changes similar to the <a href="https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/panic_threshold" target="_blank" rel="noreferrer noopener">panic threshold</a> to make this disappear entirely.</li>
+
+
+<li><em>IP Address Mapping</em>. The static mapping of IP address to server type worked well for 2+ years, but it will likely need to be adjusted as we <a href="https://www.oracle.com/news/announcement/uber-selects-oracle-cloud-infrastructure-2023-02-13/" target="_blank" rel="noreferrer noopener">move our workloads to the cloud</a>.</li>
+</ul>
+
+
+<p>Interestingly, two services overwrote the default load providers to emit custom load metrics based on background job processing. This proves that the defaults worked well for most services, but the solution was flexible enough to support other use cases.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-summary"><strong>Summary</strong></h1>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/arrmQ21tVj4fLv6DVkrkdoYxp0bRT0f1Ab5Ha98zym8rjLVCbLymSXDdqyP_RJxBlIg5KE6zaAxzjYWdmgmq13h5M-GPgiEWTF5EczSNYkmFjn3sw0EiMlh97DhB32wtW0vjRSUqRGdPjC-rRQ_sebU" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 11: Zone Weights rollout.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>The project delivered very significant efficiency wins. We can run our containers at higher utilization levels, and load imbalance is no longer problematic for stateless workloads. The hardware configuration improvements resulted in double wins from reduced imbalance and pure compute capacity.</p>
+
+
+<p>More interestingly, from the engineering blog perspective, the project also resulted in several learnings.</p>
+
+
+<p>The primary one was the importance of data. The problem was real, but we started the project under the wrong assumptions. We didn’t know how to measure it; once we agreed, we lacked the tools to measure it effectively, especially over the long term. Even after that, we realized the underlying way we collect samples from the underlying infrastructure was flawed. At the same time, the data won arguments, helped us hone in on issues, and prioritized the work with other teams. Another data lesson was to set up the data infrastructure right for the long term–it helped during the project but also before. We were able to use an existing data warehouse as a base, and now afterward we periodically get questions about the load imbalance. A link to the dashboard usually answers all the questions.</p>
+
+
+<p>The second lesson was to add workarounds in the right place of the stack to get the data we needed. Building proper real-time observability would have taken us months or quarters. Still, we quickly got the right conclusions with a targeted hack and selectively basing the observations on a sample of services. Related to that was the willingness to do a lot of manual grunt work: to build the understanding, we spent weeks staring at dashboards and verifying assumptions before we started coding. Later, when implementing ALB and Zone/Cluster weights, we started with relatively small changes, verified assumptions, and iterated to the next version.</p>
+
+
+<p>The third, arguably less generalizable lesson, was to trust in the platforms. We made a bet that our microservices would migrate to the common frameworks. Similarly, when implementing, we built on top of years of pre-existing investments in the platform–pre-existing tooling (dashboards, debug tooling, operational knowledge, rollout policies) was there, and we could roll out major changes reasonably quickly and safely. We built with the grain of the platform and avoided major rewrites that could have derailed the project.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-acknowledgments"><strong>Acknowledgments</strong></h2>
+
+
+<p>There were many people involved in the project. We thank Avinash Palayadi, Prashant Varanasi, Zheng Shao, Hiren Panchasara, and Ankit Srivastava for their general contributions. Jeff Bean, Sahil Rihan, Vikrant Soman, Jon Nathan, and Vaidas Zlotkus for hardware help, Vytenis Darulis for observability fixes, Jia Zhan and Eric Chung for ALB reviews, Nisha Khater for per-instance-stats project, Allen Lu for rolling out yarpc globally.</p>
+
+
+<p class="has-small-font-size">Logo attribution: “<a href="https://www.flickr.com/photos/141290938@N03/26682754214" target="_blank" rel="noreferrer noopener">Scales of Justice – The Law – Lawyers and Attorneys</a>” by <a href="https://www.flickr.com/photos/141290938@N03" target="_blank" rel="noreferrer noopener">weiss_paarz_photos</a> is licensed under <a href="https://creativecommons.org/licenses/by-sa/2.0/?ref=openverse" target="_blank" rel="noreferrer noopener">CC BY-SA 2.0</a>.</p>
+https://www.uber.com/blog/load-balancing-handling-heterogeneous-hardware/https://www.uber.com/blog/load-balancing-handling-heterogeneous-hardware/Thu, 07 Mar 2024 07:00:00 GMTUberEngineeringBackendNetwork IDS Ruleset Management with Aristotle v2<h1 class="wp-block-heading" id="h-introduction">Introduction</h1>
+
+
+<p>If you were to ask a veteran SOC (Security Operations Center) analyst about Network IDS (Intrusion Detection Systems) or IPS (Intrusion Prevention Systems), the response would probably contain phrases such as <em>“too many alerts,”</em> and <em>“false positives.”</em> At Uber, we face these same challenges of volume, accuracy, and manageability. Multiple times a day, more than 90,000 IDS rules are parsed, analyzed, updated, filtered, and deployed to our network sensors. <a href="https://github.com/secureworks/aristotle/releases/tag/v2.0.0" target="_blank" rel="noreferrer noopener">Aristotle v2</a> was created to enable us to automate this process, apply induction-based intelligence extraction, and enhance rule metadata to reduce false positives and help ensure that appropriate IDS alerts receive proper attention.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-overview">Overview</h2>
+
+
+<p>The IDS ruleset update process at Uber involves multiple steps, as shown in Figure 1. Collating and distributing rules is straightforward and common to all Suricata™ deployments. Deciding which rules to include and how they should be modified is what happens in step 4, “Filter Rulesets,” and will be the focus of this blog.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/6EfyApi87FAXsUWWOQm_9Dx78vMvI3h_N7q8faeJeghq0NI_U1tlQEGEXVwcKik1oxxRBBGJbhjjQ3SEhL9Cx4hPIwFHr8yUcMaXKLVdmz4DbRINAF4LBgk92UJKZAR993YpZQ3IsPgMauY88YLib5I" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption"><em>Figure 1: IDS Ruleset Update Process.</em></figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-background">Background</h2>
+
+
+<p>IDS alerts are generated by IDS engines operating on logic governed by rules (or “rulesets”). At a basic level, IDS rules can be thought of as advanced pattern matching against network traffic and connection state. The most popular open source Network IDS engines are <a href="https://suricata.io/" target="_blank" rel="noreferrer noopener">Suricata</a> and <a href="https://snort.org/" target="_blank" rel="noreferrer noopener">Snort</a>™. This article focuses on Suricata, but the concepts and practices can also apply to Snort.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-ids-rule-selection-approaches">IDS Rule Selection Approaches</h2>
+
+
+<p>Choosing which rules to apply to particular sensors can have a significant impact on false positive rates, undesired IDS alerts, and engine performance. For example, sensors protecting a pool of Linux® web servers don’t need to be running rules designed to detect attacks that target Windows® file sharing.</p>
+
+
+<h3 class="wp-block-heading" id="h-rule-classification">Rule Classification</h3>
+
+
+<p>Historically, ruleset consumers have used two big “knobs” when it comes to choosing which rules to enable or disable. The first is the “classtype,” a native rule keyword with a finite set of options, which are defined by the ruleset provider and attempts to categorize the rule. Usually, no more than a few dozen classtype categories are defined, and common values include “trojan-activity,” “attempted-dos,” and “bad-unknown.” The second knob is the filename of the file that the rule is placed in by the ruleset provider, who will often segregate rules into different files with names like “sql.rules,” “scan.rules,” and “trojan.rules.”</p>
+
+
+<p>A major problem with these “knobs” is that they don’t allow for a one-to-many mapping. Each only supports a single value for a single rule. This lack of flexibility can be restrictive. For example, should a rule that detects recently seen exploit kit activity go into the “current-events.rules,” “exploit.rules,” or “web-client.rules” file (just to name a few options)? A similar challenge exists for the “classtype” field, where the activity being detected could legitimately be classified into multiple categories. These finite, blunt rule classification mechanisms are too broad to support the ruleset fine tuning flexibility needed for modern deployments.</p>
+
+
+<h3 class="wp-block-heading" id="h-manual-review">Manual Review</h3>
+
+
+<p>In order to optimize rulesets for particular environments, they must be tuned. Often this results in a non-trivial, ongoing, and manual effort. In fact, some companies have a daily task of manually inspecting each new rule, deciding if it should be included, and then tuning it as necessary. However, this quickly becomes onerous and manifestly doesn’t scale, especially if existing rules have to undergo regular re-tuning as well.</p>
+
+
+<h3 class="wp-block-heading" id="h-metadata">Metadata</h3>
+
+
+<p>There exists a “metadata” keyword, supported by IDS engines like Suricata and Snort, that allows for arbitrary key-value pairs to be embedded into each rule. This can be extremely helpful in deciding which rules to enable because rules can be filtered based on the content of the metadata. Suricata will also include the metadata in the IDS alert, which can be used for more informed post-processing, decision making, and correlation.</p>
+
+
+<p>Metadata key-value pairs provide distinct advantages over traditional rule categorization, including:</p>
+
+
+<ul><li><strong>One-to-many mapping:</strong> For example, the “protocols” metadata key can have values “http” and “tcp”</li>
+
+
+<li><strong>Arbitrary key names and values:</strong> Classification doesn’t have to be limited to pre-defined, finite options</li>
+</ul>
+
+
+<h4 class="wp-block-heading" id="h-a-better-way">A BETTER Way</h4>
+
+
+<p>The <a href="https://better-schema.readthedocs.io/" target="_blank" rel="noreferrer noopener">BETTER</a> (Better Enhanced Teleological and Taxonomic Embedded Rules) schema for key-value based IDS rule metadata was proposed in 2019. It recognized the need for one-to-many metadata mappings, and attempted to bring some structure and standardization to commonly used metadata keys and (in some cases) values. One vendor—<a href="https://www.secureworks.com/" target="_blank" rel="noreferrer noopener">Secureworks</a>®—fully implemented BETTER in its Suricata ruleset offering, while other vendors such as <a href="https://rules.emergingthreats.net/" target="_blank" rel="noreferrer noopener">Proofpoint ET Pro</a>®, have rulesets with partial compatibility. BETTER never received widespread industry adoption, but its major concepts persist, and the use of metadata for ruleset filtering is still a solid strategy.</p>
+
+
+<p>Many ruleset providers do populate metadata, but almost all of them do so in a way that severely limits the effectiveness of using metadata as a means of rule filtering. Specifically, the rulesets have one or more of the following shortcomings:</p>
+
+
+<ul><li><strong>Missing metadata</strong>: Either applicable metadata key-value pairs are not used in the ruleset, or metadata key-value pairs are applied selectively instead of universally. Filtering rulesets based on metadata is most useful if all applicable metadata are applied to all applicable rules, and utility falls off sharply when this is not the case. For example, setting the metadata “attack-target http-server” on 20 rules in the ruleset when there are 400 more rules that could be classified the same way, makes filtering based on that key-value pair of limited value.</li>
+
+
+<li><strong>Inconsistent value formatting</strong>: For example, “cve” key values may appear as “cve_2023_1234,” “cve_2023_1234_cve_2023_2468,” “2023_1234,” “2023-1234,” etc. Without a normalized nomenclature, accurate filtering becomes challenging.</li>
+
+
+<li><strong>Poor value formatting</strong>: This includes things such as not using standard datetime formats like <a href="https://www.iso.org/iso-8601-date-and-time-format.html" target="_blank" rel="noreferrer noopener">ISO 8601</a> when specifying time/date strings.</li>
+</ul>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-aristotle-v1">Aristotle v1</h2>
+
+
+<p>In 2019, <a href="https://www.secureworks.com/" target="_blank" rel="noreferrer noopener">Secureworks</a> released <a href="https://github.com/secureworks/aristotle/releases/tag/1.0.5" target="_blank" rel="noreferrer noopener">Aristotle (v1)</a>, an open source Python tool that allowed users to “filter” (enable or disable) rules based on metadata key-value pairs. By using a concrete boolean algebra, “filter strings” can be defined to control rule selection. This can be quite powerful, but the usefulness of Aristotle v1 is limited by the richness (or rather, lack thereof) of the metadata in the provided rules, something controlled by ruleset vendors and onerous to maintain manually. Since most ruleset vendors do not provide comprehensive metadata and/or do not have metadata with the precision and consistency needed for accurate programmatic filtering, something more than Aristotle v1 is needed.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-metadata-and-beyond">Metadata and Beyond</h1>
+
+
+<h2 class="wp-block-heading" id="h-aristotle-v2">Aristotle v2</h2>
+
+
+<p>Uber recently contributed significant improvements to <a href="https://github.com/secureworks/aristotle/" target="_blank" rel="noreferrer noopener">Aristotle</a>, resulting in <a href="https://github.com/secureworks/aristotle/releases/tag/v2.0.0" target="_blank" rel="noreferrer noopener">Aristotle v2</a>. These updates added support for metadata normalization, enhancement, and manipulation. Figure 2 shows the different components of Aristotle v2, which will be discussed in more detail.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/xD-k_zGYrP0E2OvjjvYtxgHwHQ7JUMBexQANRA_Eu2aYPDpoMzEIrchMQf6wgIw2xjEyog4IaHfNg6sV20TwqA3Y71iIrf_Pd8w1_vgx7AWalDiYxSbndXriycNrLGhRqS_Gr3r2kjZ46tzqJqN6zOM" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption"><em>Figure 2: Aristotle v2 components.</em></figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-filtering">Filtering</h3>
+
+
+<p>Aristotle v1—which is basically the “Filter Rulesets” step—did a good job of supporting boolean filtering on metadata, and even included the ability to specify numerical relationships for certain keys (e.g., “created_at > 2023-01-01”). To the list of keys that support such comparisons, Aristotle v2 added <strong>risk_score</strong> (more on that key later). </p>
+
+
+<p>Additionally, the ability to do regular expression based filtering was introduced in Aristotle v2. While this does impact filtering performance because it adds non-literal elements to the boolean expression, it does provide powerful and often needed capability. Specifically, regular expression matches can be applied to the entire rule with the “rule_regex” keyword, or scoped to just the “msg” field with the “msg_regex” keyword.</p>
+
+
+<h3 class="wp-block-heading" id="h-normalization">Normalization</h3>
+
+
+<p>To address the filtering challenges that come from a lack of consistent metadata value format, Aristotle v2 supports the normalization of certain metadata key values. Specifically, the following normalizations are supported:</p>
+
+
+<ul><li><strong>CVE</strong> key value(s) normalized to format <em>YYYY-<num></em>. If multiple CVEs are represented in the value and strung together with a “_” (e.g., “cve_2021_27561_cve_2021_27562” [<em>sic</em>]), then all identified CVEs will be normalized and included.</li>
+
+
+<li>Values from the non-BETTER schema keys <strong>mitre_technique_id</strong> and <strong>mitre_tactic_id</strong> will be put into the standards compliant <strong>mitre_attack</strong> key. </li>
+
+
+<li>Date key values—determined by any key names that end with “_at” or “-at”, e.g., <strong>created_at</strong>—will be attempted to be normalized to ISO 8601 format <em>YYYY-MM-DD</em>.</li>
+</ul>
+
+
+<h3 class="wp-block-heading" id="h-enhancement">Enhancement</h3>
+
+
+<p>While normalizing metadata is necessary and useful, it can’t address the issue of missing metadata. However, a rule is more than its metadata, so we asked the question, “<em>can we identify, deduce, induce, or otherwise infer particulars from the rule’s ontology, and augment the rule metadata with that information?</em>” This led to creating the ability of Aristotle v2 to analyze the ontology of each rule and add/update the metadata with the following <a href="https://aristotle-py.readthedocs.io/en/latest/usage.html#enhance" target="_blank" rel="noreferrer noopener">enhancements</a>:</p>
+
+
+<ul><li><strong>flow</strong> key with values normalized to be either “to_server” or “to_client”</li>
+
+
+<li><strong>protocols</strong> key and applicable values</li>
+
+
+<li><strong>cve</strong> key and applicable values. The value(s) are based on data extracted from the raw rule, e.g., “msg” field, “reference” keyword, etc.</li>
+
+
+<li><strong>mitre_attack</strong> key and applicable values. The value(s) are based on data extracted from the rule’s “reference” keyword</li>
+
+
+<li><strong>hostile</strong> key and applicable values (“dest_ip” or “src_ip”)—the values are the inverse of values taken from the “target” keyword</li>
+
+
+<li><strong>classtype</strong> key and applicable values</li>
+
+
+<li><strong>filename</strong> key and applicable values—the value will be the filename the rule came from, if the rule was loaded from a file</li>
+
+
+<li><strong>originally_disabled</strong> key and boolean value get added on each rule internally, to be used for filtering</li>
+
+
+<li><strong>detection_direction</strong> key (see below)</li>
+</ul>
+
+
+<h4 class="wp-block-heading" id="h-detection-direction">Detection Direction</h4>
+
+
+<p>While network IDS rules can be unidirectional, the overwhelming majority of them are written to target just one side of the client-server communication. Additionally, rules are typically scoped by specifying IP address groups for the source and destination. IP address groups are user-defined but almost always include the variables “HOME_NET” and “EXTERNAL_NET.” The idea is that HOME_NET is the group of IP addresses owned by the user or company, and intended to be protected; and EXTERNAL_NET is the group of IPs “outside” the user’s network, typically the general Internet. EXTERNAL_NET is often (but not necessarily) defined as everything that isn’t specified in HOME_NET.</p>
+
+
+<p>The <strong>detection_direction</strong> metadata key attempts to normalize the directionality of traffic on which the rule detects. To do this, the source and destination sections of the rule are processed and reduced down to “$HOME_NET”, “$EXTERNAL_NET”, “any”, or “UNDETERMINED”, and used to set the <strong>detection_direction</strong> value as seen in Figure 3.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/rwHiJEqmAcq7pqON8pnrpt2Tp9XmvhGxRSe5Vcc-i1bpiIPwjm73jvH_0raA3E9dWOkzWzd4C3vlaM7oeCUvzUacl8uKFArxQSCNCb71h1-QLfNXZD736JMmp7FwkeLGdFhj5jZZajAfVmwdP0SbDoU" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption"><em>Figure 3: detection_direction values and conditions.</em></figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Knowing a rule’s “detection direction” is important in being able to determine the significance and seriousness of what it is detecting. For example, consider a rule that detects traffic known to be generated by devices infected with the Mirai malware. Such traffic seen inbound (coming from EXTERNAL_NET and directed to HOME_NET) can usually be classified as scanning and considered to be little more than Internet noise. Yet such traffic seen outbound (coming from HOME_NET and directed to EXTERNAL_NET), is a good indication that there is an infected device on your network and it is part of an active botnet. The latter case is more serious than the former and should be treated as such. The rule and its associated IDS alert need to be able to communicate these realities. Accurately classifying rules and their IDS alerts so that they can be programmatically responded to is important, and this is where Post Filter Modification comes into play.</p>
+
+
+<h3 class="wp-block-heading" id="h-pfmod-post-filter-modification">PFMod (Post Filter Modification)</h3>
+
+
+<p>Aristotle v2 offers the option to further filter and modify the ruleset after normalization, enhancement, and initial filter string application. This is known as PFMod (<a href="https://aristotle-py.readthedocs.io/en/latest/post_filter_mod.html" target="_blank" rel="noreferrer noopener">Post Filter Modification</a>) and allows for the identification of rules based on filter strings, and then particular “actions” taken on those rules.</p>
+
+
+<h4 class="wp-block-heading" id="h-pfmod-actions">PFMod Actions</h4>
+
+
+<p>PFMod actions include the ability to add/delete metadata, enable/disable rules, set priority, and do a regular expression based “find and replace” on the full rule. Supported PFMod actions include:</p>
+
+
+<ul><li><strong>disable</strong>: Disable the rule.</li>
+
+
+<li><strong>enable</strong>: Enable the rule. Note that for “disabled” rules to make it to PFMod for consideration, they must first match in the initial filter string matching phase.</li>
+
+
+<li><strong>add_metadata</strong>: YAML key-value pair where the (YAML) value is the metadata key-value pair to add, e.g. “protocols http”. Note that if there is already metadata using the given key, it is not overwritten unless the value is the same too, in which case nothing is added since it already exists.</li>
+
+
+<li><strong>add_metadata_exclusive</strong>: YAML key-value pair where the (YAML) value is the metadata key-value pair to add (e.g., “priority high”). If the given metadata key already exists, overwrite it with the new value.</li>
+
+
+<li><strong>delete_metadata</strong>: If a metadata key-value pair is given (e.g., “former_category malware”), remove the key-value pair from the rule. If just a metadata key name is given (e.g., “former_category”), remove all metadata using the given key, regardless of the value(s).</li>
+
+
+<li><strong>regex_sub</strong>: Perform a regular expression find and replace on the rule.</li>
+
+
+<li><strong>set_<keyword></strong>: Set the <em><keyword></em> in the IDS rule string to have the given value. If the rule does not contain the given keyword, add it and set the value to the given value. Supported keywords include “priority,” “sid,” “gid,” “rev,” “msg,” “classtype,” “reference,” “target,” “threshold,” and “flow.” For integer keywords (“priority,” “rev,” “gid,” and “sid”), relative values can be used by preceding the integer value with a ‘+’ or ‘-’. For example, the action ‘set_priority “-1″‘ will cause the existing priority value in the rule to be decreased by 1.</li>
+
+
+<li><strong>set_<arbitrary_integer_metadata></strong>: Similar to “add_metadata_exclusive,” allows for the setting or changing of an arbitrary integer-based metadata key value, but also supports relative values, along with default values. Format shown in Figure 4.</li>
+</ul>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/cDFJsx8a4aR3fzcHxzT5t7BZxYGOGfujqynX60OfUBJAWhp_kRonpAJJymbKHMKiwUzKGqDCVOlqw5YiAe6XLh6PfDVvMeAUWV3vwCTgRpSBLFmsNjhRAw9nfA-NBrRJppAEuYIlP9T7Fq-5apCTUAg" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption"><em>Figure 4: PFMod action syntax for setting arbitrary integer-based metadata.</em></figcaption></figure></div>
+
+<p>Notes:</p>
+
+
+<ul><li>The <em><arbitrary_integer_metadata></em> string corresponds to the metadata key name and must contain at least one underscore (‘_’) character.</li>
+
+
+<li>The metadata key being referenced should have a value corresponding to an integer.</li>
+
+
+<li>A preceding ‘+’ or ‘-‘ to the given <value> will cause the existing metadata value in the rule to be increased or decreased by the given <em><value></em>, respectively. If the metadata key does not exist, then the value will be set to the given <em><default></em> value, if provided, otherwise no change will be made.</li>
+
+
+<li>Examples show in Figure 5.</li>
+</ul>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/8H_XGd2h-bhRh3_3TU3DOSXxru4ndUFegnldYy6niuSgJxr5fuWo721rruZzI-nUFTGNo0g9RMEwEXPthNZQxvrqa_Anwi37gcTuely-ZGlcZopCI8gu0RmZOQhsWioYFRD-BR16fG8Bonr4HgUdV_w" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption"><em>Figure 5: Example PFMod actions setting arbitrary integer-based metadata key-value pairs.</em></figcaption></figure></div>
+
+<h4 class="wp-block-heading" id="h-pfmod-rules">PFMod Rules</h4>
+
+
+<p>PFMod conditions and actions are controlled by PFMod rules (not to be confused with IDS “rules”). PFMod rules are defined in YAML files and are processed in a depth-first, linear fashion. This means that you can define actions that apply broadly to many (or all) rules, and then have more specific PFMod rules that apply more precise actions to subsets of those rules. As shown in Figure 6, PFMod rules files can “include” other PFMod rules files for easy organization.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/qYBdFR47BWVJxSUSy7f1-35up1H8fsOESih8Vy2oX_MT0mjf-dKWSyd83FEhgW-2tVZTOpZyeuaKX1zTCHarBkDhuI92DMehaMcs1gmrXy2rhsQ0V00a8HPQz3EOkEM9J_IYm4pcvklTxDtSiMiqyoQ" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption"><em>Figure 6: Example file using </em><strong><em>include</em></strong><em> to load multiple PFMod files.</em></figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>In addition to <strong>include</strong> statements, a PFMod rule file can contain multiple rules. Figure 7 shows an example PFMod rule file that updates IDS rules and metadata.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/3omcuZfAMQjK8WXdHLOLj1ITew4Nu75Ha9jPFbjPZiV7aIo3jYiHTTQY0lN0txuMFxS-VCJMtnSZegFxZux-XxMphuu4gZHLjBkaAMutOjnO66o_liREiFfbWrn2mbT9bib9G-1X-Cwz8GiAOocgNy4" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption"><em>Figure 7: Example PFMod file with </em><strong><em>rules</em></strong><em> specified.</em></figcaption></figure></div>
+
+<h4 class="wp-block-heading" id="h-risk-score">Risk Score</h4>
+
+
+<p>Each Suricata rule that is deployed at Uber receives a “risk score.” These risk scores are automatically generated at ruleset compile time and applied as metadata values by PFMod rules. Rule metadata, including <strong>risk_score</strong>, are included in Suricata alerts and play an important role in event processing. More on this later.</p>
+
+
+<h3 class="wp-block-heading" id="h-maintenance">Maintenance</h3>
+
+
+<p>When new rules are added to the rulesets used at Uber—which happens daily—they are automatically subjected to our existing Aristotle v2 pipeline which includes filtering and the application of non-trivial PFMod logic to shape and classify each rule accordingly. Thus, manual analysis and tweaking of each new rule is avoided by using Aristotle v2 as a reliable “set it and forget it” mechanism. Of course, judicious occasional revisiting of ruleset filtering and PFMod logic is done to align the ruleset with the current environments and expected traffic patterns.</p>
+
+
+<h3 class="wp-block-heading" id="h-documentation">Documentation</h3>
+
+
+<p>More details about Aristotle v2 and how to use it can be found in the <a href="https://aristotle-py.readthedocs.io/en/latest/" target="_blank" rel="noreferrer noopener">online documentation</a>.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-aggregation-correlation-risk-score-and-alerting">Aggregation, Correlation, Risk Score, and Alerting</h1>
+
+
+<p>Uber processes billions of events a day, including hundreds of thousands of IDS alerts. Events come from myriad sources including log files, vendor products, in-house systems, custom detections, and sensing technologies like IDS. Security related events, referred to as “signals,” receive a “risk score” value that is represented by a single integer and associated with the signal. The risk score value for a signal plays a non-trivial role in downstream aggregation and correlation algorithms that ultimately determine if a signal or group of signals qualify for a formal meta-alert requiring a response. In other words, the “risk score” value quantifies the necessity and appropriate level of response. Depending on the level warranted, responses typically take the form of a manual investigation by a security analyst, and/or a series of programmatic actions in a Security Orchestration And Response (SOAR) pipeline.</p>
+
+
+<p>The evaluation, aggregation, and correlation of signals at Uber is a sophisticated process (not to mention the response pipelines), the intricate details of which are outside the scope of this article. However, the general strategy revolves around what we call “Entity Based Alerting.” For a given time window, signals are grouped by entity (e.g., IP address, host, user, etc.) and a correlation algorithm is applied to determine if an actionable meta-alert should be created. The risk score values from individual signals play a significant part in this calculation, as they are weighted and added together, and ultimately compared against a threshold used to make a final determination. The weighting of signals—which can be thought of as adjusting risk scores up or down—is based on sundry criteria, including entity characteristics, and often involves correlation with other data sources. For example, signals for a user entity where the user is an Administrator are weighted higher than those related to a non-Administrator user. Similarly, a signal involving an IP address entity from a known sanctioned vulnerability scanner will be weighted lower, while an event involving an IP address entity that is known to be part of an isolated network responsible for financial transactions will be weighted higher. Note that given a high enough risk score and/or weighting modification, a single signal can be enough to generate a meta-alert and response.</p>
+
+
+<p>In practice, aggregating and correlating signals related to common entities has shown to be an effective way to identify events and combinations of events worth responding to. With IDS alerts, Aristotle v2 plays a crucial role in being able to choose which rules are enabled, what metadata is included, and what risk score value each rule should carry. IDS alert metadata, especially the risk score value, allows Suricata alerts to be better managed so that analysts are not overwhelmed with alerts or false positives.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-conclusion">Conclusion</h1>
+
+
+<p>By using Aristotle v2 to normalize, enhance, and manipulate rule metadata, rules can be accurately described, programmatically understood, and willfully modified. Applying concrete boolean algebra against metadata key-value pairs results in powerful filtering capabilities that allow us to curate Suricata rulesets to only run applicable rules in particular environments. Rules are automatically tuned based on explicit and inferred teleological motivations and ontological realities. Custom metadata values such as “risk_score” are intelligently added to each rule which enables effective downstream correlation such that false positives are minimized and notable alerts receive appropriate attention. The result is a scalable, controllable, and accurate Suricata ruleset management and response solution.</p>
+https://www.uber.com/blog/network-ids-ruleset-management-with-aristotle-v2/https://www.uber.com/blog/network-ids-ruleset-management-with-aristotle-v2/Thu, 29 Feb 2024 07:00:00 GMTUberEngineeringBackendBuilding Scalable, Real-Time Chat to Improve Customer Experience<h1 class="wp-block-heading" id="h-introduction">Introduction</h1>
+
+
+<p>Uber is a global business and has a customer base that’s spread throughout the world. Uber’s customer base is divided into many user personas, predominantly riders, drivers, eaters, couriers, and merchants. Being a global business, Uber’s customers also expect support at a global scale. We have customers reach out to us through various live (chat, phone) and non-live (inApp Messaging) channels, and expect swift resolutions to their issues. With millions of support interactions (known internally as <em>contacts</em>) being raised by Uber customers every week, our goal is to resolve these contacts within a predefined service level agreement (SLA). Contacts created by customers are resolved either via automation or with help from a customer support agent. </p>
+
+
+<p>For agent contacts, the cost of resolution of tickets plays an important role in how Uber structures its support channels and determines volumes across different live and non-live channels. Cost-per-contact (CPC) and FCR (first contact resolution) for the chat channel are most effective across different live channels, as they allow agents to handle multiple chat contacts concurrently while maintaining a lower average cost than channels like Phone. This channel is in the sweet spot for Uber, as it has a good <a href="https://www.qualtrics.com/au/experience-management/customer/what-is-csat/" target="_blank" rel="noreferrer noopener">CSAT</a> score (customer satisfaction rating, measured in the range of 1 to 5) while generally reducing CPC. This channel allows for a higher automation rate, higher staffing efficiency (as agents can work on multiple chats at the same time), and high FCR, which are all beneficial to Uber while providing quality support for customers.</p>
+
+
+<p>Historically, from 2019 to early 2023, 1% of all contacts were served via live chat channel, 58% were served via inApp messaging channel (a non-live channel), and the rest were served via another live channel such as Phone. To achieve higher CSAT and FCR, the engineering team needed to scale the chat infrastructure to meet the demands of Uber’s growing business, as well as facilitate the migration of a large volume of in-app messaging and phone channel contacts to a chat channel. We will focus on the Chat live channel for this article.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-challenges">Challenges</h2>
+
+
+<p>To scale the chat channel to support 40+% of the Uber contact volume which is routed to Agents, the following were some of the major challenges the team was facing:</p>
+
+
+<ol><li>Reliability issues with delivering messages from backend systems to an agent’s browser<ol><li>46% of events originating from a customer trying to reach an agent were not delivered in time, resulting in delays for both customers and wastage of the agent’s bandwidth. Note that 46% does not indicate the number of unique contacts here but the overall number of events across all the chat contacts. </li>
+</ol>
+</li>
+
+
+<li>Missing Insights<ol><li>The observability to track the health of the chat contacts was unavailable.</li>
+
+
+<li>Since agents were idle for large amounts of time but queues were also not empty, Ops was left wondering if they were overstaffed or if it was a tech issue resulting in disproportionate volumes (referred to as a tech vs staffing issue).</li>
+</ol>
+</li>
+</ol>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-legacy-architecture-related-challenges">Legacy Architecture Related Challenges</h2>
+
+
+<p>Our legacy architecture was built using the <a href="https://wamp-proto.org/index.html" target="_blank" rel="noreferrer noopener">WAMP protocol</a> that was used primarily for message passing and PubSub over WebSockets to relay contact information to the agent’s machine.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img decoding="async" loading="lazy" width="1024" height="416" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Fig1_old_arch-1-1024x416.png" alt="" class="wp-image-1078909" style="aspect-ratio:2.2164502164502164;width:700px;height:auto" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Fig1_old_arch-1.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Fig1_old_arch-1.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Fig1_old_arch-1.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Fig1_old_arch-1.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Fig1_old_arch-1.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 1: Describes the previous high-level flow of the chat contact from being created to being routed to an agent on the front end. </figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p><em>Note: This is different from the data path involving the exchange of chat messages between the customer and Uber Support, facilitated through HTTP Server-Sent Events (SSE). For this purpose, Uber utilizes Ramen as an internal service, serving a dual role in the control and data paths. In the control path, Ramen provides bi-directional support for client-to-mobile use cases, allowing effective communication. Simultaneously, in the data path, Ramen offers </em><a href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events" target="_blank" rel="noreferrer noopener"><em>SSE</em></a><em> capabilities for client-to-web use cases.</em></p>
+
+
+<p><em>However, a noteworthy distinction arises in the data path, specifically for client-to-web use cases, where Ramen demonstrates a successful delivery rate of 94.5%. It operates in a unidirectional manner, prompting the necessity for new control flows. These new control flows are essential to detect and manage situations where the client is no longer responsive, thereby addressing the unidirectional limitation in the data path. In this blog, we will cover the new control flow to deliver the events from the </em>backend to the <em>Agent’s browser (Web) to enable the agent for the first reply.</em></p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>The team launched the E2E architecture on production, and it started to see issues. Not immediately, but as traffic scaled beyond the few tickets coming through, the team realized that the architecture could not scale beyond its initial capabilities easily and production management was not so straightforward. Listed below are some of these core issues:</p>
+
+
+<h3 class="wp-block-heading" id="h-reliability">Reliability</h3>
+
+
+<p>We were facing reliability issues with our 1.5X scaled traffic, resulting in up to 46% of events from the backend not being delivered to the Agent’s browser. This added to the customer’s wait time to speak to an agent.</p>
+
+
+<h3 class="wp-block-heading" id="h-scale">Scale</h3>
+
+
+<p>Beyond a low RPS of around >~10, the system performance to deliver contacts from the backend deteriorated significantly due to high memory usage or file descriptor leaks. Horizontal scalability was not supported due to limitations with the older versions of WAMP Library being used, and upgrading the same was a huge effort.</p>
+
+
+<h3 class="wp-block-heading" id="h-observability-debuggability-nbsp">Observability/ Debuggability </h3>
+
+
+<p>The following were the major issues related to Observability:</p>
+
+
+<ol><li>It was difficult to track the health of the chat contacts i.e. if chat contacts are missing the SLA due to Engineering related concerns or Staffing related concerns.</li>
+
+
+<li>Chat contacts were not onboarded on the Queue-based architecture resulting in over 8% of the chat volume not being routed to any Agent due to the agent’s attribute matching flow.</li>
+
+
+<li>The WAMP protocol and libraries (<a href="https://github.com/crossbario/autobahn-js">eg1</a>, <a href="https://github.com/gammazero/nexus/tree/v2">eg2</a>) used were deprecated and did not provide a lot of insights into inner workings, resulting in debugging being much more difficult. Furthermore, we did not have Chat contact lifecycle debugging implemented end to end, & we were unable to accurately detect Chat SLA misses on the platform overall.</li>
+</ol>
+
+
+<h3 class="wp-block-heading" id="h-stateful">Stateful</h3>
+
+
+<p>The services were stateful, complicating maintenance and restarts, which caused spikes in message delivery time and losses. The WebSocket proxy was added to perform authorization, and also because services overall were stateful, this, however, increased latency tremendously. The double socket proxy caused issues when either side disconnected. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-tech-requirements">Tech Requirements</h2>
+
+
+<p>Following were some of the goals the tech team was working towards:</p>
+
+
+<ol><li>Scale up Chat traffic from 1% to 40% of the overall contact volume by the end of 2023 (1.5 million tickets per week)<ol><li>Onboard and Scale the Chat traffic on Queues to support the Insight related to Queues</li>
+
+
+<li>Scale to handle over 80% of Uber’s overall contact volume by the end of 2024 (3 million tickets per week).</li>
+</ol>
+</li>
+
+
+<li>Reservation (connecting a customer to an agent on the first try after an agent has been identified) success via the proxy pipeline (known as the Push Pipeline) should be >= 99.5%</li>
+
+
+<li>Build observability and debuggability over the entire Chat flow, end to end.</li>
+
+
+<li>Stateless services that would not need recalibration if they horizontally scaled or if instances went down for any reason</li>
+</ol>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-solution">Solution</h2>
+
+
+<p>The new architecture needed to be simple to improve transparency into its inner workings and for the team to be able to easily scale. The team decided to go ahead with the Push Pipeline, which would be a simple, no-redundant WebSocket server that agent machines would connect to and be able to send and receive messages through one generic socket channel.</p>
+
+
+<h3 class="wp-block-heading" id="h-high-level-architecture">High-Level Architecture</h3>
+
+
+<p>The new architecture as it exists today is showcased below:</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="517" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Fig2_new_arch-1024x517.png" alt="" class="wp-image-1078914" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Fig2_new_arch.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Fig2_new_arch.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Fig2_new_arch.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Fig2_new_arch.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Fig2_new_arch.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 2: Describes the new high-level flow following the journey of the chat contact being created through being routed to an agent on the front end.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>The architecture has the following parts:</p>
+
+
+<h3 class="wp-block-heading" id="h-front-end">Front End</h3>
+
+
+<p>Front End UI is used by agents to interact with customers. Widgets and different actions are available to agents to investigate and take appropriate actions for the customer.</p>
+
+
+<h3 class="wp-block-heading" id="h-contact-reservation">Contact Reservation</h3>
+
+
+<p>Router is the service that finds the most appropriate match between the agent and contact. Upon finding the most suitable contact for an agent, the contact is pushed into a reserved state for the agent.</p>
+
+
+<h3 class="wp-block-heading" id="h-push-pipeline">Push Pipeline</h3>
+
+
+<p>Upon successful reservation of the contact for the agent, the matched information is published to Apache Kafka®. On receiving this information through the socket via GraphQL subscriptions, Front End loads the contact for the agent along with all necessary widgets and actions enabling the agent to respond to the user.</p>
+
+
+<h3 class="wp-block-heading" id="h-agent-state">Agent State</h3>
+
+
+<p>Any agent who needs to start working needs to go online via a toggle on Front End, which when triggered updates the Agent State service with the relevant agent’s new state.</p>
+
+
+<h3 class="wp-block-heading" id="h-edge-proxy">Edge Proxy</h3>
+
+
+<p>Any connection between the client browser and backend services happens via the Edge Proxy which safeguards Uber services as a firewall and proxy layer.</p>
+
+
+<h3 class="wp-block-heading" id="h-ease-of-operations-and-better-insights">Ease of Operations and Better Insights</h3>
+
+
+<p>The following are the important points:</p>
+
+
+<ol><li>Onboarded the Chat traffic on the Queues where subscribed Agents will receive the contacts based on the concurrency set of the Agent’s profile. Concurrency defines the number of chat contacts that an agent can simultaneously work on.</li>
+
+
+<li>Agent staffing to Queues becomes determinant in nature and features such as SLA Based Routing (Prioritizing chat contacts based on Queue SLA), Sticky Routing (Sticking reopen contacts with the Agents) and priority routing (prioritizing based on different rules defined on the Queues) were supported by default.</li>
+
+
+<li>With Queue onboarding, dashboards were repurposed/enhanced for Ops teams to view Chat Queues SLA and agent availability & their real-time status, including the contact lifecycle states, Queue inflow/outflow, agent’s session counts, etc.</li>
+</ol>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-gql-subscription-service">GQL Subscription Service</h2>
+
+
+<p>The major highlights related to the GraphQL subscriptions are:</p>
+
+
+<h4 class="wp-block-heading" id="h-reconnection-on-disconnection">Reconnection on Disconnection</h4>
+
+
+<p>We have enabled ping pong on the GraphQL subscription socket to make sure that the socket is disconnected automatically in the case of a non-reliable connection. When the socket is disconnected, the respective agent becomes ineligible to receive new contacts. Web socket reconnection is reattempted automatically. Upon successful reconnection, all the reserved/assigned contacts are fetched so the agent can accept them.</p>
+
+
+<h4 class="wp-block-heading" id="h-push-pipeline-reliability-nbsp">Push Pipeline Reliability </h4>
+
+
+<p>For the reserved contact for a given agent, if the front end does not send back an acknowledgment to the chat service, we try to reserve the same contact for another available agent. We check if the web socket and http protocols are working properly for the agent’s browser by sending the heartbeat over the GraphQL subscriptions, the response to which is sent via an HTTP API call from the agent’s browser to check if the agent is online.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-technical-choices">Technical Choices</h2>
+
+
+<p>Outlined below are some of the tech choices we made to improve the reliability and robustness of the chat system, while also considering the end-to-end latency impact of our choices on the user’s perceived wait time. For this, we needed to keep this system simplified, while enabling select product enhancements.</p>
+
+
+<h3 class="wp-block-heading" id="h-using-graphql-over-websocket-with-graphql-subscriptions">Using GraphQL over websocket with GraphQL subscriptions</h3>
+
+
+<p>The front-end team utilizes GraphQL extensively for HTTP calls on its front-end services. This led the team to select GraphQL subscriptions for pushing data from the server to the client. The client would send messages to the server via subscription requests and the server, on matching queries would send back messages to the agent machines. More about the GraphQL subscription is covered in the below sections.</p>
+
+
+<p>The <a href="https://github.com/enisdenjo/graphql-ws" target="_blank" rel="noreferrer noopener">graphql-ws</a> library gave us confidence because it had <a href="https://www.npmjs.com/package/graphql-ws" target="_blank" rel="noreferrer noopener">2.3m weekly downloads</a>, was <a href="https://www.apollographql.com/docs/react/data/subscriptions/#setting-up-the-transport" target="_blank" rel="noreferrer noopener">recommended by Apollo</a>, and had 0 open issues. It is also modeled on the standard <a href="https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md" target="_blank" rel="noreferrer noopener">GraphQL over WS protocol</a> and aligns its options completely over it, making it an ideal candidate for usage here.</p>
+
+
+<h3 class="wp-block-heading" id="h-stateless-services">Stateless services</h3>
+
+
+<p>The new services that would be created would need to be stateless to horizontally scale and without needing to rebalance every now and then.</p>
+
+
+<h3 class="wp-block-heading" id="h-websocket-without-http-fallback">Websocket without HTTP fallback</h3>
+
+
+<p>Since the system required bidirectional communication between agent machines and the proxy layer, having HTTP fallback would not really make any difference to the SLAs of the system. Hence, the team focused on increasing the availability of socket connections with the proxy via: </p>
+
+
+<ol><li>Bidirectional ping pong messages to prevent hung sockets</li>
+
+
+<li>Backed off reconnects after disconnects to prevent concurrent reconnects from overwhelming the service.</li>
+
+
+<li>Single proxy to connect sockets without any handover </li>
+</ol>
+
+
+<h3 class="wp-block-heading" id="h-using-apache-kafka-as-a-message-service-on-the-backend">Using Apache Kafka® as a message service on the Backend</h3>
+
+
+<p>The contact messages already flowed through various services through Kafka before reaching the proxy layer. It was decided to continue & extend the usage of Kafka as it was reliable, fast & supported broadcasting (PubSub) capabilities.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-testing-amp-launch">Testing & Launch</h1>
+
+
+<p>We have performed both functional and non-functional tests to ensure both customers and agents are provided with the best experience end to end. To predict performance, a few of the tests that were done before launch were:</p>
+
+
+<h3 class="wp-block-heading" id="h-load-tests">Load tests</h3>
+
+
+<p>A ~10K socket connection could be established from a single machine, which will further be horizontally scalable as we add more machines. We tested successfully to push the event at 20X of the old stack.</p>
+
+
+<h3 class="wp-block-heading" id="h-shadow-traffic-flows">Shadow traffic flows</h3>
+
+
+<p>Existing traffic was directed through both the old system and the new pipeline to test its capacity with 40,000 contacts and 2,000 agents daily. This process revealed no problems, and data metrics showed that latency and availability were satisfactory and met the desired thresholds.</p>
+
+
+<h3 class="wp-block-heading" id="h-reverse-shadow-traffic-flows">Reverse shadow traffic flows</h3>
+
+
+<p>Existing traffic was directed through the new system with the old user interface for agents, serving as a crucial reliability test. This was the initial use of the new system, and it successfully managed the traffic while maintaining latency within the defined SLAs.</p>
+
+
+<p>As we went along, we encountered unique system and agent behavior issues and did some fixes to increase reliability and reduce latency on the pipeline overall. Some of the major issues were:</p>
+
+
+<h3 class="wp-block-heading" id="h-deletion-of-cookies-from-the-browser">Deletion of cookies from the browser</h3>
+
+
+<p>Browser cookies, when cleared, created issues related to auth and subsequent API failures, which prevented the pushed events from being acted upon by the front end. Agents used to remain online without working on any contacts in such cases.</p>
+
+
+<h3 class="wp-block-heading" id="h-bugs-in-auto-logout-flows">Bugs in Auto-Logout Flows</h3>
+
+
+<p>Agents used to not be logged out because of issues such as out of order or missing events. Agents who finished their work for the day remained online in the system if they simply closed their tabs. This caused increases in customer wait times as the pipeline tried to push events to these agents who weren’t online. We then started automatically logging agents out based on recent acknowledgment misses and tracing logouts overall to the right causes to improve confidence in the system.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-results">Results</h2>
+
+
+<p>The Chat channel has been able to scale to about <strong>36%</strong> of the overall Uber Contact volume which is routed to Agents, with more coming in the months ahead. It seems the team has regained the trust for scaling the Chat channel, as well as improving the overall customer experience around it. The team was also able to massively improve reliability, with the error rate of delivering the contact being around 46% in the old stack to roughly 0.45% in the new one. With each failed delivery, the customer’s ticket bounced back with the 30 seconds of delay, after which delivery was retried, and bringing this number down sub 0.45% at scale was massive for customer and agent experience overall.</p>
+
+
+<p>We’ve also had other wins in this area, with perhaps the best one being simplicity. The new architecture has <strong>fewer services, fewer protocols, and better observability</strong> built into the system for visibility into contact delivery metrics, delay within the system, and end-to-end latency.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-conclusion-and-next-steps">Conclusion and Next Steps</h1>
+
+
+<p>The new push pipeline enables the team to onboard other push use cases and opens up doors to improve user experience by providing real-time information for agents to act upon. Some use cases relating to Greenlight appointments and agent work overlaps on contacts will soon move on this new stack as a part of the next phase.</p>
+
+
+<p>Further improving the user experience for the Chat channel will also happen as a whole, focusing on both enhancements and system architecture adjustments. This will be done based on learnings from the expansion of the product and addressing issues reported by customers and agents.</p>
+
+
+<p class="has-small-font-size"><em>The cover image was found at this link: <a href="https://openverse.org/image/2b3fadf3-2490-4a0c-906d-f7cf1c13a4cb?q=customer%20support">source</a></em></p>
+https://www.uber.com/blog/building-scalable-real-time-chat/https://www.uber.com/blog/building-scalable-real-time-chat/Tue, 20 Feb 2024 07:00:00 GMTUberEngineeringBackendWebHow Uber Serves Over 40 Million Reads Per Second from Online Storage Using an Integrated Cache<h1 class="wp-block-heading" id="h-introduction">Introduction</h1>
+
+
+<p><a href="https://eng.uber.com/schemaless-sql-database/" target="_blank" rel="noreferrer noopener">Docstore</a> is Uber’s in-house, distributed database built on top of MySQL®. Storing tens of PBs of data and serving tens of millions of requests/second, it is one of the largest database engines at Uber used by microservices from all business verticals. Since its inception in 2020, Docstore users and use cases are growing, and so are the request volume and data footprint. </p>
+
+
+<p>The growing number of demands from business verticals and offerings introduces complex microservices and dependency call graphs. As a result, applications demand low latency, higher performance, and scalability from the database, while simultaneously generating higher workloads.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-challenges">Challenges</h2>
+
+
+<p>Most of the microservices at Uber use databases backed by disk-based storage in order to persist data. However, every database faces challenges serving applications that require low-latency read access and high scalability.</p>
+
+
+<p>This came to a boiling point when one use case required much higher read throughput than any of our existing users. Docstore could have accommodated their needs, as it is backed by NVMe SSDs, which provide low latency and high throughput. However, using Docstore in the above scenario would have been cost prohibitive and would have required many scaling and operational challenges.</p>
+
+
+<p>Before diving into the challenges, let’s understand the high-level architecture of Docstore.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-docstore-architecture">Docstore Architecture</h2>
+
+
+<p>Docstore is mainly divided into three layers: a stateless query engine layer, a stateful storage engine layer, and a control plane. For the scope of this blog, we will talk about its query and storage engine layers. </p>
+
+
+<p>The stateless query engine layer is responsible for query planning, routing, sharding, schema management, node health monitoring, request parsing, validation, and AuthN/AuthZ. </p>
+
+
+<p>The storage engine layer is responsible for consensus via Raft, replication, transactions, concurrency control, and load management. A partition is typically composed of MySQL nodes backed by NVMe SSDs, which are capable of handling heavy read and write workloads. Additionally, data is sharded across multiple partitions containing one leader and two follower nodes using Raft for consensus.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/GBkXOF__0QtOHj5Bkl_OeqGLk9LRI9iDFVs6e3J_eZJBuvIPUBGBQCGzIcwJISdPj-jIDeYjjByFDh9m5OBobGXhZYkU4xEQIP7MDQf9-iPDp0p1oOOYniJuDvo7BJeMgP-oabTjG37spd5tJFw18B8" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 1: Docstore architecture.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Now let’s look at some of the challenges faced when services demand low-latency reads at a high scale: </p>
+
+
+<ol><li><strong>Speed of data retrieval from disk has a threshold:</strong> There’s a limit to how far one can optimize application data models and queries to improve database latency and performance. Beyond that, squeezing out more performance is not possible. </li>
+
+
+<li><strong>Vertical scaling: </strong>Assigning more resources or upgrading to better hosts with higher performance has its limitations where the database engine itself becomes a bottleneck.</li>
+
+
+<li><strong>Horizontal scaling:</strong> Splitting shards further across more numerous partitions helps solve the challenges to an extent however doing so is an operationally more complex and lengthy process. We have to ensure data durability and resiliency without any downtime. Also this solution doesn’t fully help to solve the issues of hot keys/partitions/shards. </li>
+
+
+<li><strong>Request imbalance:</strong> Oftentimes the incoming rate of read requests is orders of magnitude higher than write requests. In such cases, the underlying MySQL node will struggle to keep up with the heavy workload and further impact latencies. </li>
+
+
+<li><strong>Cost:</strong> Vertical and horizontal scaling to improve latencies are costly in the long term. Costs are multiplied 6x to handle each of the 3 stateful nodes across both regions. Additionally, scaling doesn’t fully address the problem.</li>
+</ol>
+
+
+<p>To overcome this, microservices make use of caching. At Uber we provide Redis™ as a distributed caching solution. A typical design pattern for microservices is to write to database and cache while serving reads from the cache for improved latencies. However, this approach has following challenges: </p>
+
+
+<ol><li>Each team has to provision and maintain their own Redis cache for their respective services</li>
+
+
+<li>Cache invalidation logic is implemented decentrally within each microservices</li>
+
+
+<li>In case of region failover, services either have to maintain caching replication to stay hot or suffer higher latencies while the cache is warming up in other regions</li>
+</ol>
+
+
+<p>Individual teams have to expend a large amount of effort to implement their own custom caching solutions with the database. It became imperative to find a better, more efficient solution that not only serves requests at low latency, but is also easy to use and improves developer productivity.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-cachefront-nbsp">CacheFront </h2>
+
+
+<p>We decided to build an integrated caching solution, CacheFront for Docstore, with following goals in mind:</p>
+
+
+<ol><li>Minimize the need for vertical and/or horizontal scaling to support low-latency read requests</li>
+
+
+<li>Reduce resource allocation to the database engine layer; caching can be built from relatively cheap hosts, so overall cost efficiency is improved</li>
+
+
+<li>Improve P50 and P99 latencies, and stabilize read latency spikes during microbursts</li>
+
+
+<li>Replace most of the custom-built caching solutions that were (or will be) built by the individual teams to answer their needs, especially in the cases where the caching is not the core business or competency of the team</li>
+
+
+<li>Make it transparent by reusing existing Docstore client without any additional boilerplate to allow benefiting from caching</li>
+
+
+<li>Increase developer productivity and allow us to release new features or replace the underlying caching technology transparently to customers </li>
+
+
+<li>Detach caching solution from Docstore’s underlying sharding scheme to avoid problems that arise from hot keys, shards, or partitions</li>
+
+
+<li>Allow us to horizontally scale out caching layer, independently of the storage engine</li>
+
+
+<li>Move ownership for maintaining and on calling Redis from feature teams to the Docstore team</li>
+</ol>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-cachefront-design">CacheFront Design</h2>
+
+
+<h3 class="wp-block-heading" id="h-docstore-query-patterns">Docstore Query Patterns</h3>
+
+
+<p>Docstore supports different ways to query by either primary key or partition key and optionally filtering the data. At a high level it can be mainly be divided into following:</p>
+
+
+<figure class="wp-block-table"><table><tbody><tr><td>Key-type / Filter</td><td>No Filter</td><td>Filter by WHERE clause</td></tr><tr><td>Rows</td><td>ReadRows</td><td>–</td></tr><tr><td>Partitions</td><td>ReadPartition</td><td>QueryRows</td></tr></tbody></table></figure>
+
+
+<p>We wanted to build our solution incrementally, beginning with most common query patterns. It turned out that more than 50% of the queries coming to Docstore are ReadRows requests, and since this also happened to be the simplest use case–no filters and point reads–it was a natural place to start with the integration.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-high-level-architecture">High-Level Architecture</h3>
+
+
+<p>Since Docstore’s query engine layer is responsible for serving reads and writes to clients, it is well suited to integrate the caching layer. It also decouples the cache from disk-based storage, allowing us to scale either of them independently. The query engine layer implements an interface to Redis for storing cached data along with a mechanism to invalidate cached entries. A high-level architecture looks like the following:</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/Rmm5BmifYPw54KnH74kaCJWK5L-FuymknafE9zQIhfeD4NpY0voHwI_3EtWXx90vPdGl63U9Ukz3ZsZQ0hwlntl55ofun8yhFL4489HMETZ2Jkkp7662u2-mIjOojJW5irCtwyb1xybqRJMlrS-2apM" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 2: CacheFront design.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Docstore is a strongly consistent database. Although integrated caching provides faster query responses, some of the semantics around consistency may not be acceptable for every microservice while using cache. For example, cache invalidation may fail or lag behind database writes. For this reason, we made integrated caching an opt-in feature. Services can configure cache usage on a per-database, per-table, and even per-request basis.</p>
+
+
+<p>If certain flows require strong consistency (such as getting items in an eater’s cart) then the cache can be bypassed, whereas other flows with low write throughput (such as fetching a restaurant’s menu) would benefit from the cache.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-cached-reads">Cached Reads</h3>
+
+
+<p>CacheFront uses a cache aside strategy to implement cached reads:</p>
+
+
+<ol><li>Query engine layer gets read request for one more rows</li>
+
+
+<li>If caching is enabled, try getting rows from Redis; stream response to users</li>
+
+
+<li>Retrieve remaining rows (if any) from the storage engine</li>
+
+
+<li>Asynchronously populate Redis with the remaining rows</li>
+
+
+<li>Stream remaining rows to users</li>
+</ol>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/TZIbPhOxvXtUMaxrn0LukNpglUsFD6CWoliV6z0OhW92wZh2wrYi6XO5-fwQyEkjGztPuGhP2j-BGxDO5Rg7MJ-lURrhwN_1Cxgt-s7i5JPNUWcm_k9s7Khb8K-_AwxOvdkni_83QqGDmuq5jOOzQC4" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 3: CacheFront read path.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-cache-invalidation">Cache Invalidation</h2>
+
+
+<blockquote class="wp-block-quote"><p><em>“There are only two hard things in Computer Science: cache invalidation and naming things.” </em></p>
+
+
+<p></p>
+<cite>– Phil Karlton</cite></blockquote>
+
+
+<p>Although the caching strategy in the previous section may seem simple, many details had to be considered in order to ensure the cache would work, especially cache invalidation. Without any explicit cache invalidation, cache entries will expire with the configured TTL (by default, 5 minutes). While this may be OK in some cases, most users expect changes to be reflected faster than the TTL. The default TTL could be lowered however this would reduce our cache hit rate without meaningfully improving consistency guarantees.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-conditional-update">Conditional Update</h3>
+
+
+<p>Docstore supports conditional updates where one or more rows can be updated based on a filter condition. For example, update the holiday schedule for all restaurant chains in a specified region. Since the results of a given filter can change, our caching layer can’t determine which rows would be affected by a conditional update until the actual rows are updated in the database engine. Due to this, we can’t invalidate and populate cached rows for conditional update in the stateless query engine layer’s write path.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-leveraging-change-data-capture-for-cache-invalidation-nbsp">Leveraging Change Data Capture for Cache Invalidation </h3>
+
+
+<p>To fix this, we leveraged Docstore’s change data capture and streaming service, Flux. Flux tails the <a href="https://dev.mysql.com/doc/internals/en/binary-log-overview.html" target="_blank" rel="noreferrer noopener">MySQL binlog</a> events for each of the clusters in our storage engine layer and publishes the events to a list of consumers. Flux powers Docstore CDC (Change Data Capture), replication, materialized views, data lake ingestion, and validating data consistency among nodes in a cluster. </p>
+
+
+<p>A new consumer was written, which subscribes to data events and either invalidates or upserts the new rows in Redis. Now with this invalidation strategy, a conditional update will result in database change events for affected rows, which will be used to invalidate or populate rows in cache. As a result, we were able to make the cache consistent within seconds of the database change, as opposed to minutes. Additionally, by using binlogs, we don’t run the risk of letting uncommitted transactions pollute the cache.</p>
+
+
+<p>The final read and write path with cache invalidation looks like the following:</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/05_8F32Yokun9_DucegrI80UJbwUwj5kulbM56xBrKCaNT2-NklDzrubhI-E7kJh3CK7Y9eQ2hggkhaXmECvSn9AZZV7ARUqiejCDk9H1SDehB_tJ3zPGmgg6UsVZKEViJM51qqqhcR-bhsS4L_DNN8" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 4: CacheFront read and write paths for invalidation.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-deduplicating-cache-writes-between-query-engine-and-flux">Deduplicating Cache Writes Between Query Engine and Flux</h3>
+
+
+<p>However, the above cache invalidation strategy has a flaw. Since writes happen to the cache simultaneously between the read path as well as the write path, it is possible that we inadvertently write a stale row to the cache, overwriting the newest value that was retrieved from the database. To solve this, we deduplicate writes based on the timestamp of the row set in MySQL, which effectively serves as its version. The timestamp is parsed out from the encoded row value in Redis (see later section on codec).</p>
+
+
+<p>Redis supports executing custom Lua scripts atomically using the <a href="https://redis.io/commands/eval/">EVAL</a> command. This script takes the same parameters as <a href="https://redis.io/commands/eval/" target="_blank" rel="noreferrer noopener">MSET</a>, however, it also performs the deduplication logic, checking the timestamp values of any rows already written to the cache and ensuring that the value to be written is newer. By using EVAL, all of this can be performed in a single request instead of requiring multiple round trips between the query engine layer and cache.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-stronger-consistency-guarantees-for-point-writes">Stronger Consistency Guarantees for Point Writes</h3>
+
+
+<p>While Flux allows us to invalidate the cache much faster than if we were relying solely on Redis TTLs for expiration of cached entries, it still provides us with eventual consistency semantics. Yet, some use cases require stronger consistency, such as reading-own-writes, so for these scenarios we added a dedicated API to the query engine that lets our users explicitly invalidate the cached rows after the corresponding writes have completed. This allowed us to provide stronger consistency guarantees for point writes, but not for conditional updates, which remain to be invalidated by Flux. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-table-schemas">Table Schemas</h3>
+
+
+<p>Before getting into more details about the implementation let’s define a few key terms. Docstore tables have a <em>primary key</em> and <em>partition key</em>. </p>
+
+
+<p>A primary key (often referred to as a <em>row key</em>) uniquely identifies a row in the Docstore table and enforces a uniqueness constraint. Every table must have a primary key, which can be composed of one or more columns.</p>
+
+
+<p>A partition key is a prefix of the entire primary key and determines which shard the row will live in. They are not completely separate–rather, partition keys are simply a part of (or equal to) the primary. </p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/3Et4lJLc7ohCnbi7oWQ5MvAnNTBN9KbRZZwVaoPf16QtK3VDpvKfr39gi4I3pdx7B5FE_IHi7Iz_tU9i4lAlEi6I_P4kPvb71vGRNxjSzCVbVe5Jr92fMfpi8tqtXh0nsqStymKUr3UymWlYmx5p9Ac" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 5: Example Docstore schemas and data modeling.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>In the example above <strong>person_id</strong> is both the primary and partition key for the <strong>person</strong> table. While for <strong>orders</strong> table <strong>cust_id</strong> is a partition key and both <strong>cust_id</strong> and <strong>order_id</strong> together form a primary key.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-redis-codec">Redis Codec</h3>
+
+
+<p>Since primarily we will be caching row reads, we can uniquely identify a row value with a given row key. Since Redis keys and values are stored as strings, we need a special codec to encode the MySQL data in a format that Redis accepts.</p>
+
+
+<p>The following codec was settled on, as it allows cache resources to be shared by different databases while still maintaining data isolation.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Screenshot-2024-02-07-at-12.36.06%E2%80%AFPM-1024x267.png" alt="" class="wp-image-1078207" referrerpolicy="no-referrer"></figure></div>
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/DYQl48pmuGDctmIRBUVlDoOQ1stF1w2I9swtVZL8SlPJZZ1jVSa7klvG_SurVWfDzwi6DE_7fwkWkWTyPqyd_8NBdd02Vv9g6j-lwp5NENw5IbSeOPeWPKCzg1WZ1uMIT6jLW7lGEmmb3WLBPE4gBLA" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 6: CacheFront Redis codec.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-features">Features</h3>
+
+
+<p>After completing the high-level design, our solution was functional. Now it was time for us to think about scale and resiliency:</p>
+
+
+<ol><li>How to verify consistency between the database and cache in real time</li>
+
+
+<li>How to tolerate zone/region failures</li>
+
+
+<li>How to tolerate Redis failures</li>
+</ol>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-compare-cache">Compare Cache</h3>
+
+
+<p>All this talk about improving consistency means nothing if it’s not measurable, so we added a special mode that shadows read requests to the cache. When reading back, we compare the cached and database data and verify that they are the same. Any mismatches–either stale rows present in the cache or rows present in the cache, but not the database–are logged and emitted as metrics. With the addition of cache invalidation using Flux, the cache is 99.99% consistent.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/5WXplUI4vPGJbSdkMGUjTl2XRN4wM8i2X6tY_SXFf_FRDWIlNCuPaTwQ-MCN-bLSWZ8k4Gp_xPZ578KB7LV8DEKvMKa6FfCByfm1BJc8_f1KRvsKuSPTnQs3KYbyj7lt2BbU6ysXVw4auVPDfoqtB30" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 7: Compare cache design.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-cache-warming">Cache Warming</h3>
+
+
+<p>A Docstore instance spawns two different geographical regions to ensure high availability and fault tolerance. The deployment is active-active, meaning requests can be issued and served in any region and all writes are replicated across regions. In case of a region failover, another region must be able to serve all requests. </p>
+
+
+<p>This model poses a challenge for CacheFront, since caches should always be warm across regions. If they are not, a region fail-over will increase the number of requests to the database due to cache misses from the traffic originally served in the failed region. This will prevent us from scaling down the storage engine and reclaiming any capacity, since the database load would be as high as it would have been without any caching. </p>
+
+
+<p>The cold cache problem can be solved with cross-region Redis replication, but it poses a problem. Docstore has its own cross-region replication mechanism. If we replicate the cache content using Redis cross-region replication, we will have two independent replication mechanisms, which could lead to cache vs. storage engine inconsistency. In order to avoid this cache inconsistency problem for CacheFront, we enhanced Redis cross-region replication components by adding a new cache warming mode.</p>
+
+
+<p>To ensure that the cache is always warm, we tail the Redis write stream and replicate keys to the remote region. In the remote region instead of directly updating the remote cache, read requests are issued to the query engine layer which, upon a cache miss, reads from the database and writes to the cache as described in the <strong>Cached Reads </strong>section of the design. By only issuing read requests upon a cache miss, we also avoid unnecessarily overloading the storage engine. The response stream of read rows from the query engine layer is simply discarded, since we are not really interested in the result.</p>
+
+
+<p>By replicating keys instead of values, we always ensure that the data in the cache is consistent with the database in its respective region and we keep the same working set of cached rows in Redis in both regions, while also limiting the amount of cross-region bandwidth used.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/cbUIurHsBaCU231zyyfsEcF0aiSL_Tqyy8x03_I3tp66sO1BwcnmPVykW93xFdePIt1JaT2ZZYWRO0RAznx0fogY1C5rahduCC5TvagTpWrxNgB7QfoKPAupt3Ts24S4EbxW9xoCaTkbCvjtdICNgKc" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 8: Cache warming design.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-negative-caching">Negative Caching</h3>
+
+
+<p>In scenarios where many of the reads are for non-existent rows, it would be good to cache the negative result instead of having a cache miss and querying the database each time. To enable this, we built negative caching into Cachefront. Similar to the regular cache population strategy where all rows returned from the database are written to the cache, we also keep track of any rows that were queried but not read from the database. These non-existent rows are written to the cache with a special flag and in future reads, if the flag is found, we ignore the row when querying the database and also do not return any data back to the user for the row.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-sharding">Sharding</h3>
+
+
+<p>Although Redis is not heavily impacted by hot partition issues, some of Docstore’s large customers generate a very large number of read-write requests, which would be challenging to cache in a single Redis cluster, typically limited in the maximum number of nodes it can have. To mitigate this, we allow a single Docstore instance to map to multiple Redis clusters. This also avoids a complete database meltdown where a large number of requests can be issued against it, in case multiple nodes in a single Redis cluster are down and cache is not available for certain ranges of keys. </p>
+
+
+<p>However even with data sharded across multiple Redis clusters, a single Redis cluster going down may create a hot-shard issue on the database. To mitigate this, we decided to shard Redis clusters by partition key, which is different from the database sharding scheme in Docstore. Now we can avoid overloading a single database shard when a single Redis cluster goes down. All requests from a failed Redis shard will be distributed among all database shards, as shown below: </p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/_NOpBAx6pbT-B-CetPrxh1Vjvj3Ref86cqNIE4WbvS00ESPzYVwI_AFpPHKFvINL6IRTZtivXpMMF5FkTuWyuAAc6ssQxp3EqkYOKh13Ici5NTl8d5U9lU02en9uYptdB902RDmBa6YBI_CloUcHwB0" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 9: Redis sharding request flows.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-circuit-breakers">Circuit Breakers</h3>
+
+
+<p>If a Redis node goes down, we’d like to be able to short circuit requests to that node to avoid the unnecessary latency penalty of a Redis get/set request for which we have high confidence that it will fail. To achieve this, we use a sliding window circuit breaker. We count the number of errors on each node per time bucket and compute the number of errors in the sliding window width.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="365" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/figure10-sliding-window-1024x365.png" alt="" class="wp-image-1078102" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/figure10-sliding-window.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/figure10-sliding-window.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/figure10-sliding-window.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/figure10-sliding-window.png 1160w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 10: Sliding window design.</figcaption></figure></div>
+
+<p>The circuit breaker is configured to short circuit a fraction of the requests to that node, proportional to the error count. Once the maximum allowed error count is hit, the circuit breaker is tripped and no more requests can be made to the node until the sliding window passes.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h3 class="wp-block-heading" id="h-adaptive-timeouts">Adaptive Timeouts</h3>
+
+
+<p>We realized that it is sometimes difficult to set the right timeouts for Redis operations. A timeout that is too short causes Redis requests to fail too early, wasting Redis resources and putting extra load on the database engine. A timeout that is too long impacts the P99.9 and P99.99 latencies, and in the worst case a request may exhaust the entire timeout that is passed in the query. While it’s possible to mitigate these issues by configuring an arbitrarily low default timeout, we risk setting a timeout too low where many requests bypass the cache and go to the database or setting a timeout too high, which leads us back to the original issue.</p>
+
+
+<p>We needed to adjust request timeouts automatically and dynamically such that the P99 of requests to Redis are succeeding within the allocated timeout, while at the same time cutting down entirely the long tail of latencies. Configuring adaptive timeouts means allowing the Redis get/set timeout value to be adjusted dynamically. By allowing adaptive timeouts, we can set a timeout equivalent to the P99.99 latency of cache requests, thereby letting 99.99% of requests go to the cache with a fast response. The remaining 0.01% of requests, which would have taken too long, can be canceled quicker and served from the database. </p>
+
+
+<p>With the enabling of adaptive timeouts, we no longer need to tune the timeouts manually to match the desired P99 latency, and instead can only set the maximum acceptable timeout limit, beyond which the framework is not allowed to go (because the maximum timeout is set by the client request anyways).</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/BFgKW0IWMozMuBjKyv8UvqNzBesswYoRMhegElEZLSlF8aBI5WT81GdZ7gHYqRX9FalcrFtlt3_Li7sd3PbxnqV5Fj0gAsl0W4SeM7-6caHi5dZDElaOvYdMEh383DXLFnnEPxPmguu5FYVS3rNaF8A" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 11: Adaptive timeouts latency improvements.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-results">Results</h2>
+
+
+<p>So did we succeed? We originally set out to build an integrated cache that’s transparent to our users. We wanted our solution to help improve latencies, be easily scalable, help curb load and costs on our storage engine and all while having good consistency guarantees.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/k8nIx9d66HktdxoS2Hl1WQHvf17lZoYz1-CBKXi9HBwVIs2JPakyPe0XZN55LnqVsDP0jJTmOWsj3iI5wiDqIfBm_ldkjXAjtBEy_ql-WeUE5l7Xs54OUEFEefGlx6P9_V3IrUZsiWlUT0HTWEE6h6A" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 12: Cache vs storage engine latency comparison.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<ol><li>Request latencies with integrated cache are significantly better. P75 latency is down 75% and P99.9 latency is down over 67% while also limiting latency spikes, as seen above.</li>
+</ol>
+
+
+<ol start="2"><li>Cache Invalidation using Flux and Compare cache mode help us ensure good consistency.</li>
+
+
+<li>Since it sits behind our existing APIs, it is transparent to users and can be managed internally while still giving flexibility to users through header-based options. </li>
+
+
+<li>Sharding and cache warming allow it to be scalable and fault tolerant. In fact, one of our largest initial use cases drives over 6M RPS with a 99% cache hit rate with a proven successful failover where all traffic was redirected to the remote region.</li>
+
+
+<li>The same use-case would have originally required approximately 60K CPU cores in order to serve 6M RPS from the storage engine directly. With CacheFront we serve approximately 99.9% cache hits with only 3K Redis cores, allowing us to reduce the capacity. </li>
+</ol>
+
+
+<p>Today CacheFront supports over 40M requests per second across all Docstore instances in production, and the number is growing. </p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/pTmRmm5OFwqZ9bmcvsp_Lskq3PTyxOP8XaRaJ-OWGrg3Vy3I4rPFX5ApmE9cOCH9kvfZZRJHfHw4r9ZM0dWj27QltRed9gQJnoPZdYhYOy-tMOec-kAhQ_452oHVYgtVqPWA66dzfu1y4ClxFraeBQM" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 13: Total cache reads across all instances.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>We’ve addressed one of the core challenges in scaling the read workload on Docstore via CacheFront. It not only made it possible to onboard large-scale use cases that demand high throughput and low-latency reads, but also helped us reduce load on the storage engine and save resources, improving the overall cost of storage and allowing developers to focus on building products instead of managing infrastructure.</p>
+
+
+<p>If you like challenges related to distributed systems, databases, storage, and cache, please explore and apply to open positions <a href="https://www.uber.com/us/en/careers/list/?query=storage&department=Engineering" target="_blank" rel="noreferrer noopener">here</a>.</p>
+
+
+<p class="has-small-font-size"><em>Oracle, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.</em></p>
+
+
+<p class="has-small-font-size"><em>Redis is a trademark of Redis Labs Ltd. Any rights therein are reserved to Redis Labs Ltd. Any use herein is for referential purposes only and does not indicate any sponsorship, endorsement or affiliation between Redis and Uber.</em></p>
+https://www.uber.com/blog/how-uber-serves-over-40-million-reads-per-second-using-an-integrated-cache/https://www.uber.com/blog/how-uber-serves-over-40-million-reads-per-second-using-an-integrated-cache/Thu, 15 Feb 2024 07:00:00 GMTUberEngineeringBackendData / MLJupiter: Config Driven Adtech Batch Ingestion Platform<h1 class="wp-block-heading" id="h-introduction">Introduction</h1>
+
+
+<p>Uber’s mission is to reimagine the way the world moves for the better and provide earning opportunities globally through its marketplace. One effective approach to bring the Uber brand and marketplace closer to people is to invest in paid marketing strategies.</p>
+
+
+<p>Achieving an optimal equilibrium in the marketplace necessitates the continuous activity of a balance between supply and demand. This requires creating an environment that is affordable for spenders while remaining a great earning opportunity for earners. One approach to accomplishing this goal is by consistently introducing new users to the marketplace, an ongoing process that involves promoting Uber’s marketplace offerings across diverse marketing platforms such as Google, Meta, Apple, and others.</p>
+
+
+<p>Given that these are paid advertisements, our marketing teams continuously develop strategies to rapidly onboard more users to the platform. Therefore, receiving timely signals from these vendors is crucial for us to refine our approach effectively.</p>
+
+
+<p>This blog post aims to explore the constraints and difficulties encountered by our legacy ingestion system, MaRS (Marketing Reporting Service), responsible for gathering ad signals from external ad partners at fixed intervals. Furthermore, we will address how we enhanced our marketing operations through technological advancements and attained scalability by implementing our new system, Jupiter.</p>
+
+
+<p>In this blog, we have described paid marketing as a domain, while ad tech represents the systems within that same domain. These terms can be used interchangeably within this context.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-what-is-the-performance-marketing-user-flow">What Is The Performance Marketing User Flow?</h2>
+
+
+<p>On a general scale, the subsequent sequence offers a thorough outline of the complete user journey: starting from engaging with the ads, navigating to the Uber platform, and culminating in a conversion. This action, valuable to our business, in our context could involve signing up on Uber, placing an order via Uber Eats, or taking a ride.</p>
+
+
+<p>Following the aforementioned action, the subsequent events are triggered:</p>
+
+
+<p><strong>Conversion event</strong>: When a user clicks on the ad to download the Uber app, marking a conversion specific to that ad. This is one type of conversion event linked to downloading.</p>
+
+
+<p><strong>Spend event</strong>: When a user views an ad, signifying expenditure to display that ad to the user.</p>
+
+
+<p>These spend events from the advertising partner need to be ingested, processed, and transmitted downstream. This is done to measure and optimize the ad’s performance.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img decoding="async" loading="lazy" width="1817" height="1363" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure1-edited-1.png" alt="" class="wp-image-1077751" style="aspect-ratio:1.2027027027027026;object-fit:contain;width:767px;height:auto" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1817,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure1-edited-1.png 1817w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure1-edited-1.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure1-edited-1.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure1-edited-1.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure1-edited-1.png 1536w" sizes="(max-width: 1817px) 100vw, 1817px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 1: User Flow in Adtech.</figcaption></figure></div>
+
+<h5 class="wp-block-heading" id="h-sample-user-flow"><strong>Sample User Flow</strong></h5>
+
+
+<ul><li>Step 1: The User Clicks on the Uber Ad on the Partner Page</li>
+
+
+<li>Step 2: The User Arrives on the Uber App [Conversion Events]</li>
+
+
+<li>Step 3: Adtech System Retrieves Data from Partner [Ingestion Platform]</li>
+
+
+<li>Step 4: Compute Performance Metrics (<a href="https://www.singular.net/glossary/return-on-ad-spend-roas" target="_blank" rel="noreferrer noopener">ROAS</a>)</li>
+
+
+<li>Step 5: Optimization Engine enhances Bidding Algorithms by adjusting them according to computed Metrics.</li>
+</ul>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-why-is-timely-ingestion-critical">Why Is Timely Ingestion Critical?</h2>
+
+
+<p>The prompt and precise ingestion of these advertising signals is crucial for Uber’s overall Performance Marketing. Even the smallest delay or inaccurate processing of timely ad signals from external partners can affect Uber’s capability to advertise on those platforms. As a result, this could influence the influx of users being onboarded onto the platform.</p>
+
+
+<p>To illustrate, during an outage lasting two days in which we were unable to ingest data from a single partner, the creation of key performance indicators (<a href="https://en.wikipedia.org/wiki/Performance_indicator" target="_blank" rel="noreferrer noopener">KPIs</a>), specifically <a href="https://www.singular.net/glossary/return-on-ad-spend-roas" target="_blank" rel="noreferrer noopener">ROAS</a>, downstream was delayed. This delay led to our machine learning algorithms in the bidding and optimization systems erroneously concluding that our ads were underperforming, causing a halt in ad spending.</p>
+
+
+<p>As a consequence, our ability to onboard new users was compromised, resulting in an imbalance in supply & demand. All this occurred due to an outage in one integration.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-problem-statement">Problem Statement</h2>
+
+
+<p>As Uber operates across numerous countries worldwide, we engage with various local and global advertising partners or advertisers for our paid marketing efforts. This has resulted in the integration of multiple diverse technological systems at different levels of technological maturity, featuring heterogeneous data schemas, formats, varied transmission protocols, and discrepancies in data freshness, lineage, and completeness.</p>
+
+
+<p>The AdTech industry is undergoing a substantial transformation where partners, Mobile Measurement Platforms (MMPs), and external ad tech platforms are transitioning from user-based ad-tracking to a spectrum of privacy-centric alternatives. This shift has given rise to a diverse ecosystem with varying standards among partners, introducing complexities such as frequent and unpredictable changes in data schemas that challenge historical assumptions in the marketing and advertising domain.</p>
+
+
+<p>This complexity has presented a compounded challenge for the ingestion system due to its rapid evolution, scale, and the diverse nature of the datasets involved.</p>
+
+
+<p>Here’s a breakdown of issue categories and the time dedicated by the ingestion team previously:</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1324" height="862" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure2-edited.jpeg" alt="" class="wp-image-1077758" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1324,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure2-edited.jpeg 1324w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure2-edited.jpeg 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure2-edited.jpeg 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure2-edited.jpeg 768w" sizes="(max-width: 1324px) 100vw, 1324px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 2: Split of Issue Categories.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-reliability">Reliability</h2>
+
+
+<p>As evident from the data, the predominant portion of time is dedicated to ensuring the reliability of the ingestion system. The primary factors contributing to this can be classified as follows:</p>
+
+
+<h3 class="wp-block-heading" id="h-high-latency-nbsp">High Latency </h3>
+
+
+<p>Ensuring prompt availability of data in the warehouse was essential for reducing our Mean Time to Detect (MTTD) anomalies and enhancing the overall performance of our ad tech systems.</p>
+
+
+<p>Due to incomplete data or data latency issues, marketers struggled to distinguish between seasonality and actual ad performance.</p>
+
+
+<h3 class="wp-block-heading" id="h-no-partial-data-availability">No Partial Data Availability</h3>
+
+
+<p>As marketing data evolves with time (such as spend data exceeding 24 hours and conversions data extending beyond 28 days), it becomes highly important to provide partial data to downstream systems. This is especially crucial in cases where issues arise from the partner’s end at specific ad account levels. Given the frequency of such issues, having this capability could have prevented numerous data outages.</p>
+
+
+<h3 class="wp-block-heading" id="h-enhancements-in-technology-stack">Enhancements in Technology Stack</h3>
+
+
+<p>The legacy systems MaRS was designed to be tightly coupled to older advertising formats/domains. Making minor improvements to MaRS used to result in extended engineering cycles or cause multiple technology regressions. Consequently, accommodating new use cases within the system resulted in its becoming unwieldy and difficult to manage. </p>
+
+
+<p>Moreover, our outdated Python®-based technology stack was causing a slowdown. Taking advantage of this situation, we initiated an upgrade.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-third-party-dependencies">Third-Party Dependencies</h2>
+
+
+<h3 class="wp-block-heading" id="h-standardization">Standardization</h3>
+
+
+<p>Out of our global and local ad partners, some have advanced APIs for data sharing. However, there are smaller partners who, due to their limited maturity, share data through more manual methods like email and SFTP, etc. Therefore, it is imperative that a single system be able to handle data ingestion from this diverse array of sources.</p>
+
+
+<p>Moreover, the data formats and Service Level Agreements (SLAs) were not consistent among all partners. This lack of standardization posed challenges for maintenance. Consequently, it was necessary to establish uniform data standards across all partners for seamless consumption by downstream systems.</p>
+
+
+<h3 class="wp-block-heading" id="h-rate-limits">Rate Limits</h3>
+
+
+<p>Introducing new partner data, onboarding new data for an existing partner, or encountering a bug in the data processing layer, requires the ingestion system to import years of historical data (backfill). This process incurred significant latency, often taking multiple days to weeks, and it also impeded the normal flow of day-to-day pipelines, due to partner rate limiting.</p>
+
+
+<h3 class="wp-block-heading" id="h-high-maintenance">High Maintenance</h3>
+
+
+<p>Sustaining partner-specific SDKs/APIs required substantial maintenance expenses, including dedicated headcount allocation, for frequent updates and bug fixes, which ultimately reduced developer productivity. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-scale">Scale</h2>
+
+
+<h3 class="wp-block-heading" id="h-huge-lead-time-to-market">Huge Lead Time To Market</h3>
+
+
+<p>Due to a substantial backlog, we could only attend to the P0 marketing requests. The backlog primarily stemmed from the fact that onboarding a new partner used to take multiple weeks, hindering our capacity for swift experimentation. </p>
+
+
+<p>For instance, in the case of an emerging partner, if we wanted to run ads on their platform, we would have to wait for several months before we had the resources to complete the onboarding process.</p>
+
+
+<h3 class="wp-block-heading" id="h-high-dependency-on-eng-nbsp">High Dependency on Eng </h3>
+
+
+<p>At present, the onboarding of any partner heavily relies on engineering resources to write boilerplate code for API integration, data transformation, validation, and testing. This consumes a significant portion of the onboarding process. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-solution-strategies">Solution Strategies</h2>
+
+
+<p>At first, MaRS was constructed with constraints tied to limited advertising spending. As Uber expanded globally, the demand for increasingly personalized marketing grew in both local and global markets. This necessitated a system that could swiftly adapt and incorporate specific nuances.</p>
+
+
+<p>Marketers needed a swifter onboarding process for new partners in our measurement pipelines to facilitate experimentation. They also sought data at a higher frequency to accelerate results, enabling them to fine-tune marketing strategies accordingly.</p>
+
+
+<p>Therefore, we developed a system to address gaps in the tech stack and accommodate future business requirements by employing a highly loosely coupled architecture.</p>
+
+
+<h3 class="wp-block-heading" id="h-build-vs-buy">Build vs. Buy</h3>
+
+
+<p>We conducted an assessment of external third-party vendors for ad signal ingestion rather than relying solely on in-house solutions. This was primarily to streamline maintenance costs.</p>
+
+
+<p>Additionally, there was a strong business directive from the marketing team to gain greater flexibility and control over primary channels (the top channels with higher spending) like Google, Apple, and Meta.</p>
+
+
+<p>As a result, we opted for a hybrid architecture that allows for a combination of external vendor data and direct in-house retrieval from partners. The decision on which approach to adopt during onboarding will be contingent on the business criticality of the integration.</p>
+
+
+<h3 class="wp-block-heading" id="h-plug-and-play-architecture">Plug and Play Architecture</h3>
+
+
+<p>We had requirements to ingest data other than existing categories of data inside adtech for various internal use cases and many short-gap solutions have been built in silo. We needed to envision a single ingestion system that is ad hoc for data sets, and we needed to do it with ease as well as with minimum effort.</p>
+
+
+<p>We incorporated plug-and-play architecture for all the components so any ingestion can change its internal component to something else with minimal effort.</p>
+
+
+<h3 class="wp-block-heading" id="h-domain-agnostic-data-ingestion">Domain Agnostic Data Ingestion</h3>
+
+
+<p>In our pursuit of creating an inclusive ingestion system for a diverse range of data, we needed to separate domain-specific intricacies and enable configurability through a fully self-service, config-based architecture.</p>
+
+
+<h3 class="wp-block-heading" id="h-reliability-0">Reliability</h3>
+
+
+<p>Dealing with a diverse range of partners, our system had to handle numerous immature data formats, inconsistent SLAs, and unexpected scenarios. The sizes of these ad signals also varied significantly, spanning from several gigabytes to terabytes in specific cases. Jupiter was specifically designed to adeptly manage these varied scenarios in a resilient manner.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-architecture">Architecture</h1>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="421" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure3-1-1024x421.png" alt="" class="wp-image-1077763" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure3-1.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure3-1.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure3-1.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure3-1.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure3-1.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 3: Jupiter Architecture.</figcaption></figure></div>
+
+<h3 class="wp-block-heading" id="h-multi-vendor-integration">Multi-Vendor Integration</h3>
+
+
+<p>We had various business scenarios requiring the integration of distinct data sets from different vendors into our platform. These integrations needed to account for specific factors such as data formats, ingestion frequencies, and data maturity levels.</p>
+
+
+<p>Consequently, the platform was architected to accommodate any vendor for any of the data ingestion processes, allowing for seamless changes with minimal configuration. </p>
+
+
+<p>Integrating a new vendor involves configuring its specific integration details, after which the rest of the platform will seamlessly connect with it.</p>
+
+
+<h3 class="wp-block-heading" id="h-multi-source-integrations-nbsp">Multi-Source Integrations </h3>
+
+
+<p>Given our interactions with numerous vendors, we naturally encountered diverse data sources that required ingestion. To address this, we implemented configurable data sources with their specific attributes defined through configuration. Just as with vendors, these data sources can be switched at any time with minimal configuration effort.</p>
+
+
+<p>Currently, we have integrations with sources like Amazon Web Services, Google Drive, email, APIs, and more. The addition of a new source involves configuring its integration details, after which the rest of the platform will seamlessly adapt to it.</p>
+
+
+<h3 class="wp-block-heading" id="h-non-transformed-data-sets">Non-Transformed Data Sets</h3>
+
+
+<p>In order to meet our business requirements, we found it necessary to ingest data over longer intervals without being constrained by partner capabilities. Additionally, our crucial need to swiftly detect any anomaly trends (MTTD) prompted us to implement a data copying process without applying any transformations.</p>
+
+
+<p>This approach enabled us to expedite debugging for any issues and efficiently backfill data when necessary.</p>
+
+
+<h3 class="wp-block-heading" id="h-config-driven-transformation-layer">Config Driven Transformation Layer</h3>
+
+
+<p>Due to the various data schemas we manage, customized transformations were crucial for standardization.</p>
+
+
+<p>A substantial part of the boilerplate code was dedicated to this particular component. To achieve a fully self-service ingestion system, we aimed to configure this component for each distinct use case.</p>
+
+
+<p>Consequently, we developed an internal library for this transformation layer. This library incorporates user-defined transformations, ranging from row-to-row, and column-to-column, to aggregate transformations. We’ve leveraged this library across internal systems and similar use cases for reusability purposes. Attached is a sample configuration.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-full"><img decoding="async" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Screenshot-2024-02-05-at-1.59.18%E2%80%AFPM.png" alt="" class="wp-image-1077942" referrerpolicy="no-referrer"></figure></div>
+
+<h3 class="wp-block-heading" id="h-self-serve-ingestion-onboarding"><br>Self-Serve Ingestion Onboarding</h3>
+
+
+<p>We’ve optimized the entire onboarding process for the ingestion flow onto the platform, transitioning it into a self-service model with essential safeguards. This transformation involved implementing <strong>trigger-based mechanisms</strong> that operate seamlessly between all components, starting from fetching data from sources, initiating transformations, conducting tests, validating and promoting after all checks, and triggering post-validation procedures. Here’s the high-level flow attached for reference.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/50cHgz3rK-Vua-iE0-r2NLsMM-sAX6Mdt6468e_JwQwyiima0Yqo_XAR8ymryQRJdW_NicyVnJ5f9_1FUVH77rGb_Lic15xQ6rl2lQxIo2bpV4ewbmaZtFC_pZuaQSTjxdEzCeq5KePOQ__W6UVl4cY" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 4: Flow Diagram.</figcaption></figure></div>
+
+<p>As a result of these improvements, the responsibility for this process has been transferred to the operations team, eliminating the necessity for continual engineering involvement.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-impact">Impact</h2>
+
+
+<p>At present, the prior system has been completely phased out and transitioned to Jupiter. Below, we present an overview of the metrics for both systems:</p>
+
+
+<figure class="wp-block-table"><table><tbody><tr><td><strong>Metric</strong></td><td><strong>Improvement %</strong></td></tr><tr><td>Onboarding Time – New Ingestion</td><td>> 90%</td></tr><tr><td>Onboarding Time – New Vendor</td><td>> 75%</td></tr><tr><td>Onboarding Time – New Source</td><td>> 75%</td></tr><tr><td>Data Ingestion Frequency</td><td>> 75%</td></tr><tr><td>Data Ingestion Latency</td><td>> 70%</td></tr></tbody></table></figure>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-conclusion">Conclusion</h1>
+
+
+<p>We’ve outlined the difficulties and potential advantages linked with ad tech domain networks, along with the process of obtaining dependable data from them and implementing intricate transformations to address various business needs. At present, we’ve retired the previous system and transitioned all use cases to the new platform, incorporating fresh data enhancements wherever feasible.</p>
+
+
+<p>We’ve successfully met our primary objective, accelerating the onboarding process for new partners and ensuring data reliability through a self-service approach for our stakeholders. However, there are still more intricate use cases to address. For instance, we’ve thus far focused on downloading a single report structure and applying transformations. Our next challenge is to download multiple structures, amalgamate them, and provide either a single or multiple datasets through a unified workflow. The next significant step is to expand this platform beyond its current specific-use-case support and transition it into a multi-tenant system.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-acknowledgments">Acknowledgments</h2>
+
+
+<p>We extend our special appreciation to both the core engineering and the product team, which includes Prathamesh Gabale (Engineering Manager), Akshit Jain (Software Engineer), Sarthak Chhillar (Software Engineer), Saurav Pradhan (Software Engineer), and Piyush Choudhary (Product Manager), for their pivotal roles in ensuring the success of this journey.</p>
+
+
+<p>We would also like to express our gratitude to Devesh Kumar, Diwakar Bhatia, and Vijayasaradhi Uppaluri for their invaluable feedback and unwavering support.</p>
+
+
+<p class="has-small-font-size"><em>Amazon Web Services, AWS, the Powered by AWS logo, and S3 are trademarks of Amazon.com, Inc. or its affiliates.</em></p>
+https://www.uber.com/blog/jupiter-batch-ingestion-platform/https://www.uber.com/blog/jupiter-batch-ingestion-platform/Tue, 06 Feb 2024 07:00:00 GMTUberEngineeringData / MLDataCentral: Uber’s Big Data Observability and Chargeback Platform<p>In this blog, we will walk you through DataCentral, Uber’s homegrown Big Data Observability, Attribution, and Governance platform. This blog gives a high-level overview of DataCentral’s key features. Before we get into the what and why of DataCentral, let’s do a quick primer of Uber’s Data ecosystem and its challenges.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-introduction-to-uber-s-big-data-landscape">Introduction to Uber’s Big Data Landscape</h1>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" loading="lazy" width="980" height="533" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-4.png" alt="" class="wp-image-1077460" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=980,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-4.png 980w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-4.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-4.png 768w" sizes="(max-width: 980px) 100vw, 980px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 1: Uber’s Big Data Landscape.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>Uber’s data infrastructure is composed of a wide variety of compute engines, scheduling/execution solutions, and storage solutions. Compute engines such as Apache Spark<sup>™</sup>, Presto<sup>®</sup>, Apache Hive<sup>™</sup>, Neutrino, Apache Flink<sup>®</sup>, etc., allow Uber to run petabyte-scale operations on a daily basis. Further, scheduling and execution engines such as Piper (Uber’s fork of Apache Airflow<sup>™</sup>), Query Builder (user platform for executing compute SQLs), Query Runner (proxy layer for execution of workloads), and Cadence (workflow orchestration engine, open-sourced by Uber) exist to allow scheduling and execution of compute workloads. Finally, a significant portion of storage is supported by HDFS, Google Cloud Storage (GCS), AWS S3, Apache Pinot<sup>™</sup>, ElasticSearch<sup>®</sup>, etc. Each engine supports thousands of executions, which are owned by multiple owners (uOwn) and sub-teams.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-challenges">Challenges</h2>
+
+
+<p>With such a complex and diverse big data landscape operating at petabyte-scale and around a million applications/queries running each day, it’s imperative to provide the stakeholders a holistic view of the right performance and resource consumption insights. </p>
+
+
+<h4 class="wp-block-heading" id="h-stakeholder-personas">Stakeholder Personas</h4>
+
+
+<p>The stakeholders of the big data ecosystem at Uber comprises of the following:</p>
+
+
+<p><strong>Job Owners: </strong>End users visit DataCentral to find out the metadata for their jobs such as duration, costs, resource consumption, query text and logs, etc. This allows DataCentral to serve as a powerful platform for debugging failed queries and applications. </p>
+
+
+<p><strong>Big Data Teams: </strong>Big data engine teams like Spark, Presto, Hive, and Neutrino leverage the DataCentral platform to get high-level insights into the number of jobs failing, bad/abusive jobs, top error reasons, blocked queries, etc. In addition, DataCentral helps them to investigate SLA breaches, incidents, and job failures. </p>
+
+
+<p><strong>Executive Leadership: </strong>DataCentral also supports business decision making by providing organization-level statistics, such as app/query level costs. It also offers information that can be leveraged to forecast hardware requirements and costs incurred.</p>
+
+
+<p>Some typical questions which go through various personas involved with the big data platforms at Uber:</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="776" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure2-1024x776.png" alt="" class="wp-image-1077555" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure2.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure2.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure2.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1520,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure2.png 1520w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 2: User Personas of Data Platforms at Uber.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-enter-datacentral">Enter DataCentral</h2>
+
+
+<p>At Uber, we have developed DataCentral, a comprehensive platform to provide users with essential insights into big data applications and queries. DataCentral empowers data platform users by offering detailed information on workflows and apps, improving productivity, and reducing debugging time. DataCentral provides the following key services for customers:</p>
+
+
+<ol><li><strong>Observability:</strong> Granular insights into performance trends, costs, and degradation signals for big data jobs.</li>
+
+
+<li><strong>Chargeback</strong>: Metrics and resource usage for big data tools and engines such as Presto, Apache Yarn<sup>™</sup>, HDFS, Apache Kafka<sup>®</sup>, etc.</li>
+
+
+<li><strong>Consumption Reduction Programs</strong>: Powers core cost reduction initiatives for Uber’s data ecosystem, such as HDFS growth reduction, Yarn usage reduction, etc.</li>
+</ol>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="730" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure3-1024x730.png" alt="" class="wp-image-1077558" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure3.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure3.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure3.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure3.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=1933,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure3.png 1933w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 3: DataCentral and Offerings.</figcaption></figure></div>
+
+<h3 class="wp-block-heading" id="h-how-does-datacentral-help-with-observability"><br>How does DataCentral help with Observability?</h3>
+
+
+<p>Data Observability provides real-time insights into compute queries and applications. Since Uber’s data ecosystem is spread across different components, we have to track metrics across engines like Presto, Spark, Hive, and Neutrino. Aggregation and tying these metrics to execution engines is also a challenge. We do this with the following offerings:</p>
+
+
+<p><strong>Time series metrics (a.k.a. Clio)</strong>: Every query run at Uber is fingerprinted and associated with a historical trend of executions (we call this in-house solution Clio). Customers can view historical trends for metrics like Costs, Duration, Efficiency, Data Read/Written, Shuffle, and much more. Having insights into historical trends allows customers to detect and debug applications faster. Further, we provide “config change markers” that allow easy correlation between config changes and changes in the historical trends (refer to Metrics trend in Figure 4). One major challenge we observed was that infrastructure introduced failures. To address this, we built observability into Yarn, HDFS, and correlation tools.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter is-resized"><img decoding="async" loading="lazy" width="1600" height="900" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-8.png" alt="" class="wp-image-1077471" style="aspect-ratio:1.7777777777777777;width:700px;height:auto" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1600,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-8.png 1600w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-8.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-8.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-8.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-8.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=1080,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-8.png 1080w" sizes="(max-width: 1600px) 100vw, 1600px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 4: Clio time series historical trends.</figcaption></figure></div>
+
+<p><br><strong>Yarn Observability:</strong> Saturated Yarn resources can cause job failures and slowness, which are difficult to debug. We offer solutions to observe and correlate the Yarn utilization in real time when applications are run. Further, we provide insights and suggestions when jobs get affected by Yarn.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="488" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure5-1024x488.png" alt="" class="wp-image-1077183" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure5.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure5.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure5.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure5.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=1732,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure5.png 1732w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 5: Application Level Yarn Queue Insights.</figcaption></figure></div>
+
+<p><br><strong>File System Observability: </strong>HDFS slowness and File-system-induced latencies are another factor causing degradations that are difficult to detect. We made changes to the Uber Hadoop client to add client-side monitoring of HDFS call counts and latencies with application-level granularity. Every developer can view the File System performance for their specific application/query, which makes the debugging process smoother. We further have correlation systems in place to capture the various infrastructure and engine metrics to root cause issues and suggest fixes–that’s for another blog.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" loading="lazy" width="1600" height="830" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-6.png" alt="" class="wp-image-1077468" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1600,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-6.png 1600w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-6.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-6.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-6.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-6.png 1536w" sizes="(max-width: 1600px) 100vw, 1600px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 6: HDFS Metrics Surfaced to Users and Engine Teams.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" loading="lazy" width="1600" height="820" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-5.png" alt="" class="wp-image-1077463" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1600,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-5.png 1600w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-5.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-5.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-5.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/image-5.png 1536w" sizes="(max-width: 1600px) 100vw, 1600px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 7: File System Insights User Interface on DataCentral.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="524" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure8-1024x524.png" alt="" class="wp-image-1077559" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure8.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure8.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure8.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure8.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure8.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 8: Historical Insights for File System Performance.</figcaption></figure></div>
+
+<h3 class="wp-block-heading" id="h-contactless"><strong>Contactless</strong></h3>
+
+
+<p>A good chunk of any data platform user’s time goes into debugging/troubleshooting failed queries and applications. To help them to efficiently troubleshoot, we developed the “Contactless: system with the following objectives:</p>
+
+
+<ol><li>Improve discoverability of errors</li>
+
+
+<li>Identify and surface the root cause, from the right layer</li>
+
+
+<li>Provide user-friendly explanations and suggestions</li>
+
+
+<li>Provide actionable workflows to resolve errors</li>
+</ol>
+
+
+<p>The service enables engine teams to add regex-based rules into the system. A rule also supports adding additional metadata, like user-friendly explanation, root cause layer, priority, etc. Once the stack traces are gathered for an application, the contactless service matches the exception trace against the rules and surfaces the most relevant message back to the user.</p>
+
+
+<p>Whenever applications fail, DataCentral parses the error logs and applies contactless rules on the stack traces. User friendly suggestions and error messages are then displayed on the DataCentral console, which enable the end user to debug and root cause failures. Furthermore, a suggestions tab indicates the best actions that can be taken to resolve the error. </p>
+
+
+<div class="wp-block-columns is-layout-flex wp-container-3 wp-block-columns-is-layout-flex"><div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"><div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="576" height="1024" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure9A-576x1024.png" alt="" class="wp-image-1077184" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=576,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure9A.png 576w, https://blog.uber-cdn.com/cdn-cgi/image/width=169,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure9A.png 169w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure9A.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=864,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure9A.png 864w, https://blog.uber-cdn.com/cdn-cgi/image/width=1044,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure9A.png 1044w" sizes="(max-width: 576px) 100vw, 576px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 9A: User Consoles for Configuring Rules.</figcaption></figure></div></div>
+
+
+<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"><div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="534" height="1024" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure9B-534x1024.png" alt="" class="wp-image-1077187" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=534,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure9B.png 534w, https://blog.uber-cdn.com/cdn-cgi/image/width=157,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure9B.png 157w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure9B.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=801,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure9B.png 801w, https://blog.uber-cdn.com/cdn-cgi/image/width=958,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Figure9B.png 958w" sizes="(max-width: 534px) 100vw, 534px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 9B: User Consoles for Configuring Rules.</figcaption></figure></div></div>
+</div>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="509" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure10-1024x509.png" alt="" class="wp-image-1077562" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure10.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure10.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure10.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure10.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure10.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 10: Contactless in Action.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-how-does-datacentral-help-with-cost-efficiency">How Does DataCentral Help with Cost Efficiency?</h2>
+
+
+<p>Cost governance and reduction at Uber are driven by two concepts: attribution and cost efficiency. </p>
+
+
+<h3 class="wp-block-heading" id="h-chargeback"><strong>Chargeback</strong></h3>
+
+
+<p>Instead of setting hard limits and budgets on teams, Uber provides high transparency into costs and resource usage on several dimensions so that the stakeholders are equipped with the right data while making decisions. Resource usage and costs are tracked at a uOwn (Uber’s ownership platform) level granularity. Furthermore, the resource usage can be dissected across different granularities such as: User, Pipeline, Application, Schedule, and Queue level. Attribution is critical in driving conservation, identification of anti-patterns, and driving critical cost-reduction initiatives.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="520" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure11-1024x520.png" alt="" class="wp-image-1077563" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure11.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure11.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure11.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure11.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure11.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 11: HDFS Consumption and Usage Insights.</figcaption></figure></div>
+
+<p><br><strong>Consumption Reduction</strong></p>
+
+
+<p>Once resources can get attributed to the right teams and owners, stakeholders have insights into metrics like: most expensive pipelines, continuously failing workloads, unnecessary compute, etc. As part of cost efficiency, we have taken up projects (such as HDFSRed, YarnRed, PrestoRed, etc.) that make automated, data-driven decisions to reduce costs. The HDFSRed project checks the access patterns of Uber’s data tables and creates Jira tickets for owners to push for table deletions and TTLs when data is not frequently accessed. Yarn and Presto reduction initiatives similarly check for anti-patterns and unnecessary compute and raise actionable Jira tickets to reduce/stop unused compute.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="640" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure12-1024x640.png" alt="" class="wp-image-1077569" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure12.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure12.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure12.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure12.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure12.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 12: Example Yarn Reduction JIRA Ticket.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-datacentral-s-scale">DataCentral’s Scale</h2>
+
+
+<p>In order to provide real-time metadata for all Uber-wide applications, DataCentral has to match the scale of the various engines at Uber. Flink jobs keep up with Engine-level scale to ingest real-time modeled data into the internal stores. With 500K Presto queries/day, 400K Spark apps/day, and 2M Hive queries/day, the data observability jobs handle 2K queries per minute and 30K RPS while reading the engine-level metrics. Further, HDFS insights handle over 10B calls per day and peak at 150K RPS (since this tracks calls on application-level granularity).The datastores have a 6-month retention span to handle the data growth and scale. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-architecture">Architecture</h2>
+
+
+<p>It is critical to provide real-time insights and metadata in order to minimize time to debug and mitigate job failures. DataCentral’s architecture consists of the following components:</p>
+
+
+<ul><li>Engines like Presto, Hive, Spark, and Neutrino emit query-level metadata to Kafka topics in real time. DataCentral has Flink jobs that constantly listen to these Kafka topics and consume any job-level metadata emitted by the engines.</li>
+
+
+<li>The Flink jobs pre-process this data in real time and combine metadata on job-level granularity across multiple sources. Finally, the data is stored in internal stores like MySQL and Docstore (Uber’s internal datastore, providing strong consistency and high horizontal scaling).</li>
+
+
+<li>DataCentral microservice stack consists of several APIs that serve a variety of use cases, such as the DataCentral UI, external teams, TTL setting on Hive tables, and much more.</li>
+</ul>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="583" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure13-1024x583.png" alt="" class="wp-image-1077572" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure13.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure13.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure13.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure13.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/02/Figure13.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 13: High-level DataCentral architecture.</figcaption></figure></div>
+
+<p>The journey of the metadata right from the engines to Observability datastores takes under 500 ms. The DataCentral UI provides insights and metadata, which are served via the MySQL and Docstore datastores. The UI supporting APIs fetch data from disparate sources and join it into unified responses, finally serving the customer-facing views.</p>
+
+
+<p>Further batch workloads are run to power modeled datasets, which provide critical cost attribution data. Data from various engines is joined with HiveMetastore, uOwn, and other metadata sources to power rich insights, which are served on the DataCentral UI to downstream teams and leveraged for cost-reduction initiatives. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-datacentral-amp-uber-s-move-to-cloud">DataCentral & Uber’s Move to Cloud</h2>
+
+
+<p>As Uber moves to cloud, our priority remains to provide cost transparency and cost reduction into the Cloud ecosystem. Furthermore, DataCentral is supporting engine teams with critical metrics for performance testing, benchmarking, and identifying degradations when moving workloads to cloud. This allows us to make the right decisions as we migrate critical jobs to the cloud. For example, File System Observability has allowed engine teams like Spark to observe the latency increase with cloud and make the right solutions to migrate. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-conclusion">Conclusion</h1>
+
+
+<p>DataCentral has been a critical tool for engineers, data analysts, and platform teams at Uber. It provides advanced analytics and granular insights into big data applications and queries. DataCentral is used by stakeholders ranging from job owners, engine on-calls, platform teams and executive leadership. The self-serve nature of the platform has made it efficient for customers to debug jobs, mitigating incidents and root cause SLA breaches. Another key offering of DataCentral is the consumption insights into big data compute and storage entities such as HDFS, Yarn, Kafka, Presto, etc. DataCentral acts as the single source of truth for stakeholders to get insights into platform-, team-, and org-level insights. Furthermore, we plan to open-source the DataCentral toolkit for broader adoption and community collaboration. </p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p class="has-small-font-size"><em>Apache®, Apache Pinot™, Apache Flink®, Apache Kafka®, Apache Hive™, Apache Hadoop®, Apache Spark™, Apache Yarn™, Kafka®, Apache Airflow™, Flink®, Hive™, Hadoop®, Spark™, Pinot™, Airflow™, and Yarn™ are either registered trademarks or trademarks of the Apache Software Foundation in the United States and/or other countries. No endorsement by The Apache Software Foundation is implied by the use of these marks.</em></p>
+
+
+<p class="has-small-font-size"><em>Presto is a registered trademark of LF Projects, LLC. No endorsement by LF Projects, LLC is implied by the use of these marks.</em></p>
+
+
+<p class="has-small-font-size"><em>Amazon Web Services, AWS, S3, the Powered by AWS logo are trademarks of Amazon.com, Inc. or its affiliates.</em><br><em>Header image: “</em><a href="https://www.flickr.com/photos/126444666@N05/14606819370"><em>New York Grand Central Station</em></a><em>” by </em><a href="https://www.flickr.com/photos/126444666@N05"><em>jensfrickephotography</em></a><em> is licensed under </em><a href="https://creativecommons.org/licenses/by/2.0/?ref=openverse"><em>CC BY 2.0</em></a><em>.</em></p>
+https://www.uber.com/blog/datacentral-ubers-observability-and-chargeback-platform/https://www.uber.com/blog/datacentral-ubers-observability-and-chargeback-platform/Thu, 01 Feb 2024 07:30:00 GMTUberEngineeringAIBackendData / MLStopping Uber Fraudsters Through Risk Challenges<h1 class="wp-block-heading" id="h-introduction"><strong>Introduction</strong></h1>
+
+
+<p>As a marketplace-based, consumer-facing app, Uber encounters a multitude of sources of fraud across its platform. In one of the most common cases of fraud, bad actors use various methods to attempt to bypass payments for Uber rides, Eats orders, and other services, like Uber for Business. When this happens, failed transactions can occur, incurring losses that affect the drivers and businesses operating on Uber.</p>
+
+
+<p>To account for the serious financial implications of payment fraud, risk management is prioritized at Uber. Reflecting the risk solution landscape within the overall tech industry, our engineers have developed complex solutions to achieve the following: </p>
+
+
+<ol><li><strong>Detect fraud: </strong>Real-time fraud detection is driven by a system of business rules which run on <a href="https://www.uber.com/blog/mastermind/" target="_blank" rel="noreferrer noopener">Mastermind</a>, Uber’s rules engine. In addition, machine learning models generate predictive scores that give insight into the probability that a user is a fraudster. </li>
+
+
+<li><strong>Mitigate fraud: </strong>Different forms of fraud mitigation are employed at Uber to act on and resolve triggered rules and threshold-passing scores, as appropriate. These involve both manual and automated strategies, and this is also where risk challenges come into play.</li>
+</ol>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-risk-challenges">Risk Challenges</h1>
+
+
+<p>Risk challenges are experiences in which the user is asked to complete a certain task or process, often to verify the legitimacy of their identity or payment method. You have likely encountered a risk challenge before, and not just on the Uber app. A common one is to enter the CVV of a credit card when making a credit card transaction. </p>
+
+
+<p>One of the main desired outcomes of risk challenges is to effectively catch bad actors. This point is self-evident: a group that encounters risk challenges should have lower rates of fraud in comparison to a control group. However, protecting against fraud is not as simple as introducing risk challenges to everyone. The nature of risk challenges is highly individualized. Given the wide scope of Uber’s users, products, and geographies, risk challenges encountered on Uber will vary from user to user. Uber applies different risk challenges to different stages of the user journey, and users in different regions of the world may encounter different risk challenges. Let us consider just one risk challenge implemented in the Uber app: penny drop verification.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading">Penny Drop Verification</h1>
+
+
+<p>Consider the scenario where Uber receives a ride request from a user who does not seem to be the owner of the debit or credit being used on the app. Based on the behavior and data of this Uber account, it seems there is a very high probability that this particular user has stolen a card that they claim to own and plan to use for the ride. </p>
+
+
+<p>In the past, Uber would detect such users who were highly likely to be fraudsters and immediately prevent them from continuing to significantly engage with the app by employing certain strict actions. In the scenario described, the ride request would be declined, and the associated payment and/or user would be restricted in some cases.</p>
+
+
+<p>On the surface level, this might seem effective in terms of avoiding payment fraud. While this strategy of strict actioning was in place, however, it became evident that it was not ideal for potential false positive users. Uber users whose access was restricted are required to contact customer service to resolve their status, which is often a resource-intensive process. </p>
+
+
+<p>Penny drop verification was introduced in the Uber app as a user-friendly method for individuals who might have previously been restricted from using the app to instead have a chance to prove ownership of their payment method. In this challenge, a user is asked to confirm to Uber two small, random authorization hold amounts before they expire within a given timeframe.<strong> </strong>Successful completion indicates that a user is likely the legit cardholder and not a fraudster. </p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="255" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/1_why_pac-1024x255.png" alt="" class="wp-image-1076561" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/1_why_pac.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/1_why_pac.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/1_why_pac.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/1_why_pac.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/1_why_pac.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 1: Throwing ban action versus risk challenge to a potentially risky user</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading">Technical Overview</h2>
+
+
+<p>The penny drop verification challenge was implemented with the goal of being both an effective and intuitive method of fraud mitigation for users using a credit or debit card as their payment method. We can summarize how we achieved this through the following design principles, which apply to not just the penny drop verification challenge, but any other good risk challenge: </p>
+
+
+<ol><li><strong>Minimize false positives:</strong> Trust good users (and not bad users). Fraudsters should not be able to pass this challenge, while well-intentioned users should be able to self-resolve and recover should they fail. </li>
+</ol>
+
+
+<ol start="2"><li><strong>Create a seamless and empathetic user experience, with just the right amount of friction:</strong> This is necessary because trade-offs may exist between the frequency and degree of risk challenges, and user satisfaction and churn. For instance, if a user is presented with a risk challenge that they deem too hard or too long to complete, they may stop using the app altogether. A frustrating user experience should be avoided without compromising fraud mitigation. </li>
+</ol>
+
+
+<p>The following screens illustrate a happy path for a legitimate user that is thrown a new penny drop verification challenge.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img decoding="async" loading="lazy" width="1024" height="373" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/2_pac_ux_screens-1024x373.png" alt="" class="wp-image-1076568" style="aspect-ratio:2.745308310991957;width:700px;height:auto" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/2_pac_ux_screens.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/2_pac_ux_screens.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/2_pac_ux_screens.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/2_pac_ux_screens.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/2_pac_ux_screens.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 2: Happy path flow of the penny drop verification risk challenge</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p>As illustrated, the challenge is integrated into the mobile user experience in a way that should not majorly interfere with the user’s intended primary action–in this case, requesting a ride–through clear instructions and simplistic actions. At the same time, “skipping” the challenge is not possible, as the user who is thrown the challenge is required to complete it. Even if the user exits out of an initiated challenge in the user interface, the status of the challenge will still be active, and the user will be continually prompted to complete it if they try to resume relevant actions. </p>
+
+
+<h3 class="wp-block-heading"><br>Triggering Flows</h3>
+
+
+<p>As aforementioned, certain risk challenges are designed for certain user journey flows on the Uber app. Two main flows where the penny drop verification challenge may be displayed:</p>
+
+
+<ol><li>When the user makes a request for either a ride or delivery order</li>
+
+
+<li>When the user adds a payment method</li>
+</ol>
+
+
+<p>The challenge is not raised for every user at every occurrence of these flows. Rather, in the case that one of these two flows is initiated, downstream services are called on to fetch user-related features and to run risk rules in <a href="https://www.uber.com/blog/mastermind/" target="_blank" rel="noreferrer noopener">Mastermind</a>. The rule results may indicate that further risk assessment is necessary, particularly to verify that the user is the owner of a specific payment method. If this occurs, backend services send an error code to the mobile side such that the user encounters mobile screens responsible for initiating the penny drop verification challenge. </p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="222" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/3_user_action_screen-1024x222.png" alt="" class="wp-image-1076570" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/3_user_action_screen.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/3_user_action_screen.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/3_user_action_screen.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/3_user_action_screen.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/3_user_action_screen.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 3: Risk challenge is initiated by a user action, like requesting a ride</figcaption></figure></div>
+
+<h3 class="wp-block-heading"><br>User Consent</h3>
+
+
+<p>After the penny drop verification challenge is deemed necessary during a triggering flow, then a modal is shown to allow the user to choose to verify their selected card. In some cases, the user may have already consented to the challenge, but has exited before successfully completing the challenge, so they must re-consent.</p>
+
+
+<p>If the user chooses to switch to another payment method, they may not be asked for further verification. This is because the action of presenting a risk challenge depends on a user’s specific payment method. Often, an Uber user adds more than one card to their account, and they may or may not be the legitimate owner of any number of them. Different payment profiles of the same user can have different challenge statuses.</p>
+
+
+<p>Once a user clicks “Verify card,” backend processes check various conditions to determine what client-side screen to show to the user in the remainder of the challenge flow. It is first necessary to confirm that data related to the selected payment method, like its UUID and the status of the penny drop verification challenge, has been saved in <a href="https://www.uber.com/blog/schemaless-sql-database/" target="_blank" rel="noreferrer noopener">Docstore</a>, Uber’s backend database. If the card is entirely new, then relevant data about the card is written to Docstore for the first time.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="429" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/4_user_consent_screen-1024x429.png" alt="" class="wp-image-1076572" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/4_user_consent_screen.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/4_user_consent_screen.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/4_user_consent_screen.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/4_user_consent_screen.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/4_user_consent_screen.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 4: Challenge conditions are checked when a user consents to a risk challenge</figcaption></figure></div>
+
+<h3 class="wp-block-heading"><br>Send Authorizations</h3>
+
+
+<p>On a screen that provides more information about the risk challenge, the user is prompted to send authorization holds. In the overall context of electronic transactions and payments, authorization holds are temporary holds placed on a certain amount of funds; they are often used to determine whether a user has enough money to complete a transaction, and thus whether Uber is able to collect a payment from that user. </p>
+
+
+<p>After the user clicks “Send authorization holds,” two small monetary amounts are issued to the user’s designated bank account using the authorization hold protocol. To initiate this process, an internal payment operation service makes a request to a specialized “payment grant” service to create two distinct grants. This is done by supplying two randomly generated amounts to be held, as well as a specified void duration.</p>
+
+
+<p>The payment grant service interacts with a payment gateway or processor, which contacts the user’s bank or card issuer to formally request temporary authorization holds to be placed on the user’s payment account, in the specified amount. If the specified void duration lapses and the fund holds are released, and the user has not successfully verified the amounts to complete the challenge, then the user will have to re-send the authorization holds.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="446" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/5_send_auths_screen-1024x446.png" alt="" class="wp-image-1076575" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/5_send_auths_screen.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/5_send_auths_screen.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/5_send_auths_screen.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/5_send_auths_screen.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/5_send_auths_screen.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 5: Authorization holds must be sent as part of the penny drop challenge</figcaption></figure></div>
+
+<h3 class="wp-block-heading"><br>Amount Verification</h3>
+
+
+<p>To successfully complete the penny drop challenge, users are required to review their bank statements and accurately enter the exact amounts of the authorization holds within the Uber app. These entered amounts are then subject to verification.</p>
+
+
+<p>Throughout this procedure, the user’s challenge status is updated within Docstore, Uber’s backend database. If the user does not successfully verify the authorization hold amounts within a certain number of attempts, they will have failed the challenge. In this case, their access to the Uber app will be restricted because we have strong indications that they are not the owner of the payment method. By contrast, if the user does successfully complete the challenge, they can seamlessly proceed with their intended actions that they had initiated before being thrown the challenge. </p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img decoding="async" loading="lazy" width="1024" height="332" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/6_enter_amounts_screen-1024x332.png" alt="" class="wp-image-1076577" style="aspect-ratio:3.0843373493975905;width:700px;height:auto" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/6_enter_amounts_screen.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/6_enter_amounts_screen.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/6_enter_amounts_screen.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/6_enter_amounts_screen.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/6_enter_amounts_screen.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 6: Authorization hold amounts must be correctly verified to pass the penny drop challenge</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading">Conclusion</h1>
+
+
+<p>We are continually fine-tuning the user experience of the penny drop verification challenge in a way that effectively mitigates risk without creating too much friction in the user experience. Through analysis of metrics like success rates and churn rates, we continually act on insights into how users are interacting with the challenges that are thrown to them. </p>
+
+
+<p>Penny drop verification is just one type of risk challenge integrated in the Uber app. Other challenges involve varying levels of difficulty. Based on what we understand of a given user and their intentions, one challenge may be considered better to use than another. Overall, risk challenges have been integral in our ongoing efforts to enhance security and user experiences on the Uber app. Its implementation has not only effectively served as a safeguard against fraud, but has also led to smoother user experiences, thus expediting onboarding for specialized offerings such as Uber for Business.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading">Acknowledgements</h2>
+
+
+<p>Thank you to the Spender Risk Team for sharing their expertise about a range of interesting engineering challenges related to fraud throughout my internship, including risk challenges. </p>
+
+
+<p>Special thanks to Diganta Sarkar, Qixiong Liu, and Susie Peng for providing insights relevant to this blog, as well as Neel Mouleeswaran and You Xu for supporting my internship and growth as a software engineer.</p>
+
+
+<p class="has-small-font-size">Cover photo attribution: Image created by Nenad Stojkovic. Image license information: <a href="https://openverse.org/image/6d3d1a77-63ba-481c-9c58-42d1c7fa9507?q=payment%20credit%20card" target="_blank" rel="noreferrer noopener">Link</a>. No changes have been made.</p>
+https://www.uber.com/blog/stopping-uber-fraudsters-through-risk-challenges/https://www.uber.com/blog/stopping-uber-fraudsters-through-risk-challenges/Thu, 25 Jan 2024 08:00:00 GMTUberEngineeringBackendMobilePalette Meta Store Journey<h1 class="wp-block-heading" id="h-introduction"><strong>Introduction</strong></h1>
+
+
+<p>The Machine Learning (ML) team at Uber is consistently developing new and innovative components to strengthen our ML Platform (Michelangelo). </p>
+
+
+<p>In machine learning, features are the data used to make model calculations and predict an outcome. You can think of them as the input to the learning model or attributes in your data that are relevant to the predictive modeling problem.</p>
+
+
+<p>When querying Uber’s data stores for feature data, it can be hard to:</p>
+
+
+<ul><li>Figure out good Uber-specific features</li>
+
+
+<li>Build pipelines to generate features</li>
+
+
+<li>Compute features in real time</li>
+
+
+<li>Guarantee that data used at training is the same as the data used for scoring predictions</li>
+
+
+<li>Monitor features</li>
+</ul>
+
+
+<p>The Uber Michelangelo feature store, called Palette, is a database of Uber-specific curated and internally crowd-sourced features that are easy to use in machine learning projects. It comes to solve all the above-mentioned challenges. Pipelines are auto-generated for feature generations and feature dispersals. Palette supports various feature computation use cases, like batch and near real time, and includes precomputed features related to cities, drivers, and riders, as well as custom features generated for the EATs, Fraud, and Comms teams. Subject to our normal data access restrictions, Uber users are able to use many of the pruned features maintained by other Uber teams or even create their own and can directly incorporate these features in their machine learning models.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="468" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/palette-architecture-e2e-engblog-figure1-1024x468.png" alt="" class="wp-image-1075931" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/palette-architecture-e2e-engblog-figure1.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/palette-architecture-e2e-engblog-figure1.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/palette-architecture-e2e-engblog-figure1.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/palette-architecture-e2e-engblog-figure1.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=1821,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/palette-architecture-e2e-engblog-figure1.png 1821w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 1: Feature Generation graph shows job computing features. Feature Ingestion graph shows ingesting data to hive and Cassandra. Feature Serving graph shows how features are served offline/online. Feature Metadata and Data Quality graph shows how featurestore metadata flows across offline and online stores.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<p><a href="https://lucid.app/lucidchart/41687c63-006b-4f8c-a524-f56d9dbb4033/edit?page=0&v=204&s=612"></a></p>
+
+
+<h2 class="wp-block-heading" id="h-palette-metastore-background"><strong>Palette Metastore Background</strong></h2>
+
+
+<p>Palette provides feature management infrastructure including feature discovery, creation, deprecation, offline and online serving setup in its Metastore.</p>
+
+
+<p>Palette Metastore is a metadata store of features where users of Palette can create, deprecate, add details about ownership/backfill/scheduling of feature generation pipelines, offline training and HDFS location. Users can specify Cassandra databases that they want to copy data for online serving along with Spark configuration, join keys, feature list along with feature metadata. Users can also include info about which features should be copied for online serving, SQL queries for generating the features from upstream dependencies and maintaining audit of changes. </p>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="592" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Feature-Spec-Metadata-Arc-eng-blog-figure2-1024x592.png" alt="" class="wp-image-1075954" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Feature-Spec-Metadata-Arc-eng-blog-figure2.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Feature-Spec-Metadata-Arc-eng-blog-figure2.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Feature-Spec-Metadata-Arc-eng-blog-figure2.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Feature-Spec-Metadata-Arc-eng-blog-figure2.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=1794,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Feature-Spec-Metadata-Arc-eng-blog-figure2.png 1794w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 2: Feature Group Update flows from Palette Metadata repository to Offline Serving system and propagates to OnlineServing Cache eventually as well as is used by various systems for ETL/Training.</figcaption></figure></div>
+
+<p><a href="https://lucid.app/lucidchart/30856e57-7aee-4c60-ac35-c3f41da4aa19/edit?page=0&v=383&s=612"></a></p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-a-closer-look-problem-and-motivation"><strong>A Closer Look: Problem and Motivation</strong></h2>
+
+
+<p>A major incident occurred in 2021 due to inadequate schema validation on Palette Metadata where a bad Metadata change was pushed, which resulted in OnlineServing breaking for major Tier1 use cases, since it was unable to load Palette Metadata during boot up.</p>
+
+
+<p>Schema validation logic used to be client side and lived in a script within the FeatureSpec repository, which is the Metadata repository for Palette customers to make metadata-related changes. Updating validation was challenging, as customer metadata updates wouldn’t pick up the latest validation always, as they didn’t rebase against the latest code changes. This led to incorrect metadata being merged into the master repository.</p>
+
+
+<p>Metadata discrepancies caused build failures for customers rebasing against master due to incorrect metadata changes being merged into master.</p>
+
+
+<p>Incident resolution took several hours due to several issues. </p>
+
+
+<ul><li>Updating Palette Metadata in OnlineServing stack. Changing a single feature group in Palette Metadata repository led to updates for all hundreds of feature groups due to lack of an incremental update system, prolonging rollbacks.</li>
+
+
+<li>Lack of schema validation. The Feature Engine on-call had to dedicate substantial time to each customer diff. Majority of on-call time was spent on assisting with metadata changes in the FeatureSpec repo. Lack of a build job to verify actual Hive table schema before merging led to failures at training time. Customers made errors when creating Palette tables, missing required columns.</li>
+
+
+<li>Offline Metadata updates. Metadata updates took over an hour after landing changes in FeatureSpec repo since entire metadata repository was getting updated even if only a minor change was made for one of the feature groups.</li>
+</ul>
+
+
+<p>These issues highlight the challenges stemming from inadequate schema validation, leading to data loss, helpdesk burden, build failures, and confusion in pipeline updates. The complex process of updating metadata and the lack of automated schema verification further compounded the problems faced by the team.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-deep-dive-meta-store"><strong>Deep Dive: Meta Store</strong></h2>
+
+
+<h3 class="wp-block-heading" id="h-feature-store-object-model">Feature Store Object Model</h3>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="580" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/figure3-2-1024x580.png" alt="" class="wp-image-1075980" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=1024,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/figure3-2.png 1024w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/figure3-2.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/figure3-2.png 768w, https://blog.uber-cdn.com/cdn-cgi/image/width=1536,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/figure3-2.png 1536w, https://blog.uber-cdn.com/cdn-cgi/image/width=2048,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/figure3-2.png 2048w, https://blog.uber-cdn.com/cdn-cgi/image/width=2072,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/figure3-2.png 2072w" sizes="(max-width: 1024px) 100vw, 1024px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 3: FeatureGroup has OnlineSpec, OfflineSpec, ComputeSpec. OnlineSpec has Snapshot Backing which underneath is backed by Cassandra or Hive Backing. OnlineFeatureServingGroup is composed of online stores and online caches. Inference Server/Palette Service references OnlineFeatureServingGroup and indirectly references FeatureGroup.</figcaption></figure></div>
+
+<p>Following are the new objects that we formally define in the new Palette Metadata system backed by protos:</p>
+
+
+<p><strong>FeatureGroup</strong>: A logical table with a collection of features for both streaming and batch features backed by daily feature snapshots in Hive tables or Cassandra for the online store.</p>
+
+
+<p><strong>Feature</strong>: A single feature corresponding to a column within the logical FeatureGroup (table).</p>
+
+
+<p><strong>Dataset</strong>: Dataset represents the metadata needed to create a table in a database/storage for a given feature group.<strong> </strong>For example, keyspace, partition key and cluster key would be the metadata needed to create a table for a given C* cluster. These would be part of the Dataset spec<strong>.</strong></p>
+
+
+<p><strong>Storage</strong>: Storage is the underlying storage technology that is referred by dataset, online feature serving group. </p>
+
+
+<p><strong>FeatureServingGroup</strong>: A logical unit of serving in the online store that guarantees a certain SLA (throughput, latency). It is a collection of Storage (Cassandra/Redis clusters) that back the Feature Groups, and a routing map of FeatureGroups to the underlying Datasets. Note that it is common in the case of very large use cases) for FeatureServingGroup to contain multiple Cassandra clusters.</p>
+
+
+<p><strong>Inference Server/Palette Service</strong>: Inference Server is the logical object holding metadata for Inference Serving for a given model within a Michelangelo project. Palette Service (a service where users can just fetch feature values without needing a model setup) similarly will hold metadata for serving via Palette Service.</p>
+
+
+<h3 class="wp-block-heading" id="h-metadata-organization"><br>Metadata Organization</h3>
+
+
+<p>We broke the setup of Metadata inside Palette Metadata repository where following files are setup to simplify customer interaction and Michelangelo on-call interaction with the metadata where customers manage offline related metadata files and Michelangelo on-calls manage online serving related metadata files.</p>
+
+
+<p><strong>Description.json</strong>: This file contains all the metadata related to offline serving as well as ownership and alerting setup backed by OfflineSpec defined above</p>
+
+
+<p><strong>Features.json</strong>: This file will cover metadata related to features with schema backed by Feature CRD</p>
+
+
+<p><strong>OnlineServing.json</strong>: This file contains all the metadata related to online serving</p>
+
+
+<p><strong>HQL</strong>: This file contains Hive Queries for generating features</p>
+
+
+<h3 class="wp-block-heading" id="h-metadata-registration"><br>Metadata Registration</h3>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/vmeacjOfttOowaOhF2PmWRwRAqaZc8tanjGFlEQBWrb1e_gbNqlhbGs8eE3U0PlrVbjx6l4d0LiTwlvhGqJKFy9VvcMMIShMj1-T59vYdh2L-0dLTChU2u7EfdTep_tKZIO97uJ2TaVN_FaQevT4WAI" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 4: Palette Metadata repository updates go through server side validation and get registered in offline serving system and pushed to OnlineServing Cache and OnlineServing stack.</figcaption></figure></div>
+
+<p><a href="https://lucid.app/lucidchart/bf529602-029f-4540-a7ed-3433cb69e3d2/edit?page=0&v=339&s=612"></a></p>
+
+
+<p>To expedite Offline and Online Metadata updates, we moved the system handling Palette Metadata updates made by customers to incrementally compute the delta of the updates, and register those updates in the OfflineServing system. </p>
+
+
+<p>Once the updates land in UAPI, we use Kubernetes based Controller to process those updates to our highly available cache Online Serving Cache called ObjectConfig. </p>
+
+
+<p>The E2E updates to Offlline and Online systems takes only 15 minutes now instead of over an hour previously, since only incremental updates are pushed and not the entire metadata repository.</p>
+
+
+<h3 class="wp-block-heading" id="h-online-serving-re-architecture"><br>Online Serving Re-Architecture</h3>
+
+
+<div class="wp-block-image"><figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="960" height="640" src="https://blog.uber-cdn.com/cdn-cgi/image/width=2160,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Palette-Meta-Store-Journey-wrapper-figure5-edited.png" alt="" class="wp-image-1075969" srcset="https://blog.uber-cdn.com/cdn-cgi/image/width=960,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Palette-Meta-Store-Journey-wrapper-figure5-edited.png 960w, https://blog.uber-cdn.com/cdn-cgi/image/width=300,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Palette-Meta-Store-Journey-wrapper-figure5-edited.png 300w, https://blog.uber-cdn.com/cdn-cgi/image/width=768,quality=80,onerror=redirect,format=auto/wp-content/uploads/2024/01/Palette-Meta-Store-Journey-wrapper-figure5-edited.png 768w" sizes="(max-width: 960px) 100vw, 960px" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 5: Schema updates for Old and New Schema propagate from Metadata Service to Read only Cache and gets loaded to OnlineServing via Loader which is referenced by Wrapper.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h4 class="wp-block-heading" id="h-metadata-unification">Metadata Unification</h4>
+
+
+<p>In the old architecture, the metadata for online serving was fragmented across various services. We decided to consolidate all the metadata for online serving in one place, which is the Palette Metadata repository. </p>
+
+
+<h4 class="wp-block-heading" id="h-interface-redesign"><br>Interface Redesign</h4>
+
+
+<p>We made an interface change to deprecate the old schema which no longer was meeting the evolving needs of the Palette online system.</p>
+
+
+<h4 class="wp-block-heading" id="h-metadata-wrapper"><br>Metadata Wrapper</h4>
+
+
+<p>We introduced a wrapper during migration for 2 main purposes: Interface adaptation and quick rollback. During the migration process, we made both versions of metadata available for Palette Online Serving. That gave us the ability to compare the metadata in memory. Because the meta loader will transform the metadata to a format better suited serving needs, the metadata in memory is different from what we see in the metadata service. Comparing the metadata in memory gave us more confidence for a safe migration. But due to the interface redesign, we needed serving logic to support both interfaces. So the wrapper was the one to translate the legacy metadata into the format of the new interface. We also introduced a kill switch to tell the wrapper which version of the metadata it should provide to the serving logic. Then we can do a quick rollback when any metadata issue happens during migration.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-migration-challenges"><strong>Migration Challenges</strong></h2>
+
+
+<ul><li><strong>Keep a smooth user experience during migration</strong>:<ul><li>We maintained scripts to automatically synchronize feature metadata between old and new systems. This could avoid data gaps when switching to the new system.</li>
+
+
+<li>Good and clean documentation was provided to help users to learn how to onboard features to the new Metadata Store.</li>
+</ul>
+</li>
+
+
+<li><strong>Track correctness for migration</strong>:<ul><li>Comparison metrics and logs were created across Feature Generation pipeline system, offline serving system to clearly articulate the differences between old and new systems. They played as a proof of evidence regarding correctness for migration.</li>
+
+
+<li>Traffic metrics were checked to make sure that no traffic comes through old systems after full migration.</li>
+</ul>
+</li>
+
+
+<li><strong>Ensuring Backward Compatibility</strong>:<ul><li>The updated metadata introduced substantial changes in data formats and APIs. To maintain backward compatibility, it was essential to create a robust common API wrapper. This wrapper could seamlessly bridge the gap between legacy code and the new codebase. Subsequently, we could transition the underlying implementations of the Common API wrapper gradually, facilitating a seamless migration process.</li>
+</ul>
+</li>
+
+
+<li><strong>Testing</strong>:<ul><li>The code modification incorporated itself into the Michelangelo team’s offline training, re-training, evaluation and prediction workflow. To guarantee the continued functionality of these integrations after the migration, it was imperative to conduct comprehensive integration testing involving all existing systems.</li>
+</ul>
+</li>
+
+
+<li><strong>Rollback Plan</strong>:<ul><li>In case the migration encounters unexpected issues or doesn’t yield the desired results, we also defined a thorough rollback plan which could minimize downtime and mitigate risks.</li>
+</ul>
+</li>
+</ul>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-result">Result</h2>
+
+
+<p>The result of the Metadata migration was that Palette Onboarding Deployment time has reduced drastically by more than 95%. In addition, time to migrate Cassandra clusters has gone down by 90% since all online serving configuration is so cleanly organized which means on-calls no longer need to scramble to figure out which feature group gets served in which Cassandra. Due to the re-architecture of the offline metadata update system so that updates are processed incrementally, time for offline metadata updates has gone from hours to minutes. Additionally, we have introduced enhanced server validation for FeatureStore CRDs and cross-CRD validation</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-conclusion">Conclusion</h1>
+
+
+<p>Overall, introduction of formal schema, consolidation of metadata, enhanced validation, and a very diligently planned migration have led to our new metadata system being easy to use for customers and Michelangelo on-calls, reducing deployment and customer onboarding time, as well as maintenance and operational costs.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-acknowledgements">Acknowledgements</h2>
+
+
+<p>This major step for Machine Learning at Uber could not have been done without the many teams who contributed to it. Huge thank you to the Feature Engine group within Uber’s Michelangelo Team, who spent 1+ year rearchitecting the Meta Store system. </p>
+
+
+<p>We also want to give a special thank you to our partners on the Michelangelo teams for making this idea a reality, as well as our former colleagues who helped initiate this idea.</p>
+
+
+<p class="has-small-font-size"><br>Header Image Attribution: The “Journey start here” image is covered by a <a href="https://creativecommons.org/licenses/by/2.0/" target="_blank" rel="noreferrer noopener">CC BY 2.0 </a> license and is credited to <a href="https://www.flickr.com/photos/40642065@N06" target="_blank" rel="noreferrer noopener">Johnragai-Moment Catcher</a>. No changes have been made to the image.</p>
+https://www.uber.com/blog/palette-meta-store-journey/https://www.uber.com/blog/palette-meta-store-journey/Thu, 18 Jan 2024 08:00:00 GMTUberEngineeringAIUber: GC Tuning for Improved Presto Reliability<h1 class="wp-block-heading" id="h-presto-at-uber">Presto at Uber</h1>
+
+
+<p>Uber uses open-source Presto to query nearly every data source, both in motion and at rest. Presto’s versatility empowers us to make intelligent, data-driven business decisions. We operate around 20 Presto clusters spanning over 10,000 nodes across two regions. We have about 12,000 weekly active users running approximately 500,000 queries daily, which read about 100 PB from HDFS. Today, Presto is used to query various data sources like <a href="https://hive.apache.org/" target="_blank" rel="noreferrer noopener">Apache Hive</a>, <a href="https://pinot.apache.org/" target="_blank" rel="noreferrer noopener">Apache Pinot</a>, AresDb, MySQL, Elasticsearch, and Apache Kafka, through its extensible data source connectors.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/N5XyfSyzOYri5u_fdYS1bptIXQKw-pEl3hGKydZVE5hyt8eh01uGA8JAG9ucliJ5y0LzNhTBF4Qi4AEVIEWghFDsjukoKzulqE8ya7rvn6-CdNveNO6FfQ3eTaiainiLNDdIWTFxBUHTk3XOrJzNjGs" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 1</figcaption></figure></div>
+
+<p>Our selection of cluster types can accommodate any request, whether for interactive or batch purposes. <em>Interactive</em> workloads cater to dashboards/desktop users waiting for the results, and <em>batch</em> workloads are scheduled jobs that run on a predefined schedule. Each of our clusters is classified based on their machine type. Most of our clusters comprise bigger machines, which are equipped with more than 300 GB of heap memory, while other clusters have smaller machines that are equipped with less than 200 GB of heap memory, and we have modified the concurrency of each cluster depending on its size and type of the machines that make it up.</p>
+
+
+<p>On a weekly basis, memory fragmentation optimization activity is carried out across all production clusters. Even though we were constantly improving fragmentation, we still suffered from constant Full Garbage collections (very long pauses) and sporadically a few out-of-memory errors. Just to give a sense of the problem, let me show you Presto Full GC, cumulative count:</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter is-resized"><img decoding="async" src="https://lh7-us.googleusercontent.com/Lf33-HkkgTVwo2C8b7Hyew2J66Q8jQKuWyORGxXqnYUGNEXVwyMEL1QEF2di5vy6R8q0bO6OSxaT2JOTNf4d1aUDBZxfKqurCoH1Btm2_KpeWBpXytDmgEyjpleFumhiNKQ2EWAf9T5RpjtbzmQvPpQ" alt="" style="aspect-ratio:1.6341030195381883;width:700px;height:auto" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 2: Presto Full GC count per day.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-overview-g1gc-garbage-collector">Overview – G1GC Garbage Collector</h2>
+
+
+<p><a href="https://www.oracle.com/technical-resources/articles/java/g1gc.html" target="_blank" rel="noreferrer noopener">G1GC</a> is a garbage collector that tries to balance throughput and latency. G1 is a generational garbage collector, which differs from the newer concurrent garbage collectors (Shenandoah, ZGC, etc.). Generational means that the memory is divided into short and long-lived objects.</p>
+
+
+<p>The first important thing to differentiate here is that there are two types of memory: stack and heap. Stack allocations are cheap because we just need to bump up a pointer, so whenever we call a function we decrement the Stack pointer (stack grows towards the bottom), once we are done with that function we just increment the pointer, and voilà, allocation and deallocation in a single statement each. On the other hand, heap allocation/deallocation is a little bit more expensive. For G1GC, allocation is similar to stack where we only need to bump up a pointer, but deallocation requires GC to run.</p>
+
+
+<p>In Java, since all objects are allocated on the heap, then what do we allocate on the stack? There it goes, the “pointer” referencing the object on the heap. Then for the heap space, G1 divides it into small sections called “regions.”</p>
+
+
+<p>G1 tries to achieve at least 2,048 regions on the heap.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/sTVuA9Zife5F9JdnTG1FZ7qzYZPr-octAgSmrUK9kXyX4HBSlLX0dLWxlbPbUJEa0jDRYyJ_X18iICObV8_mLzcwwms9hX2_aGvVt6xGzeN7plfcLu4temYrbJKZIn9gJIKPTmb4h3D8CnmrmXVA2LM" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 3: Heap is divided into regions.</figcaption></figure></div>
+
+<p>What’s the size of each region? It depends on your heap size, but it can go from 1-32 MB. The JVM decides which size ensures that we have 2,048 regions (or more).</p>
+
+
+<p>Each region can be the young generation, the old generation, or the free.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/svWLIMAX1Kir9QJm1LdSXfmem2BefIL5uDqQmlnwbeuyZnXoQMPVaW9cEk2V0PkPOaPAwcEuw7h6eIFVbHq89XMIslU749z1QZhA_ZcRkpr-J5r6aRpyadiPUHyk8_OqKq6tStH5M2eQAwb7PiVxoLI" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 4: Heap regions are categorized as young gen, old gen, or free.</figcaption></figure></div>
+
+<p>Finally, the young generation is also divided into Eden and survivors. Eden is where any new allocation happens. For survivors, it would create two different arenas. Why? Young Gen’s approach to clear memory is copying objects between regions, so it needs an empty survivor to copy memory.</p>
+
+
+<p>So the full process is whenever we do a new Object(), it gets allocated on the Eden. GC runs and the object is not dead, so it gets copied to Survivor0. The next time GC runs again and the object is still not dead yet, it gets promoted to Survivor1. So it continues to copy back and forth between survivors until it eventually gets promoted to the old generation.</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/40pVmoyFKnSCgWh-D2aCCGDmQ_-x9Dj-DCtLP0-P28wkn2hNabgQo0yO4_06wjJqxaPQaCNs2sYePWwU0K83RrBQKDOHDLviyXy8ssi6Sqs98Lv-KTEQKU5VRmiz85YTVzYUCUFFO5fODVP18W8lFQs" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 5: Heap is fully divided into all the mentioned types.</figcaption></figure></div>
+
+<p>To recap, the young generation uses a copying mechanism to release memory. So when do we allocate to the old generation? There are two scenarios:</p>
+
+
+<ol><li>G1 has an age threshold. Every time a young gen object gets copied, we increase the age. Once we hit the threshold, it gets copied to the old gen.</li>
+
+
+<li>Each region is 1-32 MB in size. Any object that is 50% or more of the size of the region gets allocated directly to the old generation. G1 calls this a humongous object.</li>
+</ol>
+
+
+<p>How does G1 clear the old generation? It uses an algorithm called “concurrent mark and sweep.” It is a graph traversal starting from the root objects (thread stacks, global variables, etc.) and goes through every object still referenced. It is essential to mention that G1 uses STAB (snapshot at the beginning), so any new object after it starts would be considered alive regardless of its real liveness. Once it finishes, G1 knows which objects are still alive, and the ones that are not can be cleaned on the following mixed collection.</p>
+
+
+<p>What? A mixed collection? Indeed. A mixed collection is a young generation collection that would include old generation regions in the process. So it copies the objects that are still alive in another old generation region. This process is critical to reduce memory fragmentation.</p>
+
+
+<p>Who determines the size of each component (Eden, survivor, old gen, etc.)? The heap is always shrinking and expanding to fulfill its job, although there are certain limits. For instance, the young generation can only be 5-60% of the total heap.</p>
+
+
+<p>Today’s discussion doesn’t require going into more advanced G1GC topics, so let’s begin with what we have done at Uber.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-g1gc-at-uber">G1GC at Uber</h2>
+
+
+<p>When Java became more used at Uber, we were using OpenJDK 8. Most of the time, the only tuning option we had to touch was <em>-XX:InitiatingHeapOccupancyPercent=X</em>. This threshold is the one that controls if G1 should start a concurrent mark and sweep cycle. </p>
+
+
+<p>It has a default value of 45%, which usually causes an increase in CPU, because any service using some cache would eventually exceed that threshold, and it would keep triggering it endlessly. For instance, service A stores all the users in memory, and that causes the Old generation to be ~60% of the total heap. Then the 45% threshold would always be met.</p>
+
+
+<p>Then how do we tune it?</p>
+
+
+<ul><li>Enable GC logs and GC metrics</li>
+
+
+<li>Look for the peak old-generation utilization after mixed collections</li>
+
+
+<li>Select a value slightly higher than that peak–usually 5-10% higher</li>
+</ul>
+
+
+<p>However, remember that Presto servers are now running on JDK 11. How do we tune them? This was our first attempt at tuning this version. Why is it different? Java introduced dynamic IHOP (InitiatingHeapOccupancyPercent). Then we no longer have a default value of 45%, and instead we have a value that can change all of the time, and it is only available in the GC logs.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-tuning-jdk-11">Tuning JDK 11</h2>
+
+
+<p>How does dynamic IHOP get calculated? It uses the current size of the young generation plus a free threshold (basic idea, it uses a slightly more complex formula). This free threshold default value is 10% of the total heap and is used as a buffer to allow GC to complete (remember concurrent mark and sweep runs along your application).</p>
+
+
+<p>The process we follow is listed below (we waited 1-2 weeks between each step to have enough data to verify our experiments). We tried the following on one cluster first to avoid affecting all our users.</p>
+
+
+<h5 class="wp-block-heading" id="h-add-more-gc-metrics"><strong>Add more GC metrics</strong></h5>
+
+
+<p>We were missing young- and old-gen utilization, so we couldn’t easily know historical data about our utilizations.</p>
+
+
+<h5 class="wp-block-heading" id="h-decrease-max-young-generation-size-from-60-to-20"><strong>Decrease max young generation size from 60% to 20%</strong></h5>
+
+
+<p>We saw the young generation expanding a few times (50% of the total heap). This caused long GC pauses and concurrent marking to take longer to run again. Concurrent marking can’t run if we are still doing mixed collections.</p>
+
+
+<p>The result?</p>
+
+
+<ul><li>Better GC pauses.</li>
+
+
+<li>Still bad concurrent marking. This happened because by decreasing the max size by 40%, we gave that to the old generation, so concurrent marking was still starting late.</li>
+</ul>
+
+
+<h5 class="wp-block-heading" id="h-increase-free-space-from-10-to-35-amp-decrease-heap-waste-from-5-to-1"><strong>Increase Free space from 10% to 35% & decrease Heap waste from 5% to 1%</strong></h5>
+
+
+<p>Let’s first talk about heap waster percentage. This tuning option by default is 5% which tells G1 that it must only release any garbage when it exceeds 5% of the total heap. Why? To avoid long GC pauses during mixed collections. When we do concurrent marking, G1 orders the old generation’s regions based on their utilization, and it first chooses the ones that have more free space, because they are faster to copy to a new region.</p>
+
+
+<p>For our 300G clusters, that translates to 15G that will never be cleaned. We decided to decrease that to 3G (<em>-XX:G1HeapWastePercent=1</em>) based on past experiences.</p>
+
+
+<p>For free space, we analyzed several GC logs and noticed that utilization stayed at 20-35% after mixed collections. Then 20% max young gen plus 35% free space would give us a threshold of 45% (100-(35+20)%). With this config, we are giving at least a 10% buffer (35 to 45%) to have some garbage to clean.</p>
+
+
+<p>The result?</p>
+
+
+<ul><li>1% seemed too much, and we started seeing long pauses of >1s. This change was helpful because, with the GC logs, we could identify that long pauses started to happen once mixed collections tried to go from 2% -> 1% garbage.</li>
+
+
+<li>35% performed well. Full GCs were reduced (~80% for this cluster).</li>
+</ul>
+
+
+<h5 class="wp-block-heading" id="h-increase-free-space-from-35-to-40-amp-increase-heap-waste-from-1-to-2"><strong>Increase Free space from 35% to 40% & increase Heap waste from 1% to 2%</strong></h5>
+
+
+<p>The result was:</p>
+
+
+<ul><li>2% heap waste gave us an additional 9G and had little impact on latencies (~50-100ms vs. 1-1.5s with 1%).</li>
+
+
+<li>40% performed slightly better than 35%, but we didn’t gain much (85-90% vs. 80%). We decided not to go even further to avoid thrashing.</li>
+</ul>
+
+
+<h5 class="wp-block-heading" id="h-try-the-same-tuning-options-on-a-different-cluster"><strong>Try the same tuning options on a different cluster</strong></h5>
+
+
+<p>We tested the same config in a new cluster and verified the behavior before trying on all of them to see the impact. We decided to grab the cluster with the most Full GCs in the past few weeks. After 24 hours of the deployment, we could already see the impact:</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/n5lWCndCnJTQfMknVsR4_H3ggMwiIIvPlA8Rwu78ojRg_XVxmr9A9P9oxI4zqGyy6YC3pxoumheJDglKnuhe2FsVjjHUnS3TIGH5cw_D9X2Z7i-uMB7qTzbTmpO2U3448MnHwL7V2fkmycOQ44POgYI" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 6: Full GCs cumulative count of a single cluster</figcaption></figure></div>
+
+<p>Before, after just a few hours, we used to start seeing Full GCs, but after these changes, we didn’t get any.</p>
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h2 class="wp-block-heading" id="h-conclusion">Conclusion</h2>
+
+
+<p>After several weeks of testing with the tuning flags presented above, we decided to use the same flags for all clusters. After the flags were added/updated, all the clusters performed optimally with minimal to no internal OOM errors. Due to this change, the reliability of Presto clusters increased, thereby reducing reruns of the queries that were earlier failing with OOM errors, which improved the overall performance of Presto clusters. The flags that we used in the final tuning are:</p>
+
+
+<p>-XX:+UnlockExperimentalVMOptions</p>
+
+
+<p>-XX:G1MaxNewSizePercent=20</p>
+
+
+<p>-XX:G1ReservePercent=40</p>
+
+
+<p>-XX:G1HeapWastePercent=2</p>
+
+
+<p>These flags are specific to the Presto use case in Uber, which was finalized after multiple tuning iterations. We expect flags to differ for each organization based on the individual workloads, and they must be tuned on a case-by-case basis. With these flags enabled, we will see more frequent Garbage collection, but they allow us to have a more reliable Presto cluster and reduce the on-call burden for the owners.</p>
+
+
+<p>For all of our clusters, we observed the following impact:</p>
+
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/OOfBVVQv5uNpRL-ar05SEf5VYhP9uDgPqSOdAxncrYtCe_vkwVPmHGsrbh4Y0emhU_a8oC5yhLqWsDb51bhLq8Diof8XWxxuDPGcuFryT79JID4BNDq1oqf8pq48YGeuZIqetI8fR66yQUX1eIr5wgw" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 7: Cumulative Old generation count per day for all clusters.</figcaption></figure></div>
+
+<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://lh7-us.googleusercontent.com/1_HSQd_ILxdScbjmI7hoQ7IpRxIxnuXlN4lgaNs87u5GhDJUjnyH_OydBRbKv_j3sOPrcAsRVOnwqn9d7J1Eeg8uxEmglD2XfP6_BnNX9XWGS73qz3_7vy4QFDLKaUlhB3e95BMp9G3JQ3-Mn6BQcDo" alt="" referrerpolicy="no-referrer"><figcaption class="wp-element-caption">Figure 8: Internal errors per day on all clusters.</figcaption></figure></div>
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+<h1 class="wp-block-heading" id="h-what-s-next">What’s Next?</h1>
+
+
+<p>Most of the Garbage collection tuning we have done has been on product-facing applications, and we haven’t paid close attention to our storage applications. Therefore, we plan to continue tuning for the other solutions Uber provides. It would be an interesting learning experience because storage applications use large heaps, which differs from what we used to tune normally. We’ll share it with the community once we have more data.</p>
+
+
+<p>GC tuning done on Presto is an example of how improving garbage collection can improve a system’s overall performance and reliability. Our next focus will be further fine-tuning GCs for Presto clusters, especially with less powerful machines where we are still experiencing some Full GCs, and improving the system’s overall reliability. </p>
+
+
+<p>All the optimizations listed are specific to the Presto deployment in Uber and can’t be directly ported to other services. The flags listed are just for demonstration purposes to understand what flags we ended up using in our tuning. Also, we will come up with some of the best practices and guidelines that can be used by all of Uber’s storage applications, depending on their general usage, which will act as a good starting point. This will empower us to improve all of our storage applications, improving overall reliability and performance.</p>
+https://www.uber.com/blog/uber-gc-tuning-for-improved-presto-reliability/https://www.uber.com/blog/uber-gc-tuning-for-improved-presto-reliability/Thu, 11 Jan 2024 08:00:00 GMTUberEngineeringData / ML
\ No newline at end of file
diff --git a/exper/raw/rss b/exper/raw/rss
new file mode 100644
index 0000000..11720f7
--- /dev/null
+++ b/exper/raw/rss
@@ -0,0 +1,2776 @@
+
+Cloud Bloghttps://cloud.google.com/blog/Cloud BlogenTue, 07 May 2024 16:00:00 +0000https://cloud.google.com/blog/static/blog/images/google.a51985becaa6.pngCloud Bloghttps://cloud.google.com/blog/Product analytics for generative AI model and media asset companies using BigQueryhttps://cloud.google.com/blog/products/data-analytics/perform-product-analysis-with-generative-ai-and-bigquery/<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Over the last year, there’s been a lot of change in the commercial image and video asset industry: New generative AI applications let users create their own still and live images based on prompts, and traditional stock-media asset providers are offering customers richer search experiences that have a deep understanding of the image/live image content and that expose it with a natural language interface. </span></p>
+<p><span style="vertical-align: baseline;">To continually push the state of the art, these organizations must use data to evolve their products rapidly, for example to: </span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Optimize still and live image generation models</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Identify inappropriate content, such as violence or nudity</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Analyze behavior to identify improvements to the user experience</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Recommend similar images or prompts based on previous activity</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Enhance static asset search capabilities</span></p>
+</li>
+</ul>
+<p><span style="vertical-align: baseline;">To do this, they need unstructured images, live images, and audio data, combined with structured user-experience data and metadata about the assets they are interacting with, whether they’re static or AI-generated.</span></p>
+<p><span style="vertical-align: baseline;">In this post, we outline a solution</span><span style="vertical-align: baseline;"> </span><span style="vertical-align: baseline;">based on our real-life engagements with leaders in the industry who operate at the scale of petabytes per day. This solution delivers several benefits:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Minimizes costs by avoiding duplicate data and storage, while facilitating AI model proximity to data for efficient inference</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Simplifies development and delivery by combining diverse data types in a unified data architecture</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Optimizes use of limited engineering resources through an integrated, scalable serverless platform that combines </span><a href="https://cloud.google.com/bigquery?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">BigQuery</span></a><span style="vertical-align: baseline;"> and </span><a href="https://cloud.google.com/storage?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Google Cloud Storage</span></a></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Allows users to augment and transform their data according to the needs of their business </span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Enables companies to develop lightweight, powerful analyses quickly and securely, to activate customer data and quickly iterate on the output of models</span></p>
+</li>
+</ul>
+<h3><strong style="vertical-align: baseline;">The challenge of unstructured data</strong></h3>
+<p><span style="vertical-align: baseline;">Generated (unstructured) image data, the (semi-structured) prompts that made them, as well as user behavior data (structured, in tables) for things like session time and frequency, are all rich in potential insights. For example, knowing which types of prompts lead to successfully generating an image — and those that don’t — provides insights into product and model development opportunities. </span></p>
+<p><span style="vertical-align: baseline;">But combining these different data types often requires advanced analytics to interpret them meaningfully. Technologies like natural language processing and computer vision are at the forefront of extracting these kinds of valuable insights. However, integrating unstructured data within an existing analytics framework of structured data, for example user behavior data in database tables, is not without its hurdles. Common challenges include:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Data security standards:</strong><span style="vertical-align: baseline;"> Adhering to stringent data security standards to protect sensitive information is crucial. These standards include applying data masking to sensitive PII data and following least-privilege security principles for data access.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Data type silos:</strong><span style="vertical-align: baseline;"> Unstructured data is often stored separately from structured data, preventing effective analysis across data types, for example, filtering media assets (unstructured) based on user profiles (structured), as they reside in separate systems.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">High-performance, scalable cloud computing resources:</strong><span style="vertical-align: baseline;"> The need for powerful computing resources is imperative to manage and analyze large unstructured datasets effectively due to the data's complexity, volume, and the potential need for real-time results. In addition, high performance networking allows for low-latency data transfers to enable the transfer of unstructured data between storage (Cloud Storage) and analytical layers (BigQuery, Vertex, etc.)</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Maintaining data integrity across layers</strong><span style="vertical-align: baseline;">: As insights are extracted from unstructured data, preserving the original source of truth and ensuring consistency across intermediate (interstitial) layers is crucial for reliable, iterative analysis.</span></p>
+</li>
+</ul>
+<h3><strong style="vertical-align: baseline;">Streamlining data integration with Cloud Storage and BigQuery</strong></h3>
+<p><span style="vertical-align: baseline;">To overcome the challenges of working with unstructured data, </span><a href="https://cloud.google.com/storage?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Cloud Storage</span></a><span style="vertical-align: baseline;"> and </span><a href="https://cloud.google.com/bigquery?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">BigQuery</span></a><span style="vertical-align: baseline;"> can be used to centralize data, using </span><a href="https://cloud.google.com/bigquery/docs/object-table-introduction"><span style="text-decoration: underline; vertical-align: baseline;">BigQuery object tables</span></a><span style="vertical-align: baseline;"> to </span><span style="vertical-align: baseline;">enable consistent data access to varied sources through one analytical platform</span><span style="vertical-align: baseline;">. Below is an example of a simple yet effective architecture that harnesses BigQuery for both metadata generation and enhancement. This approach uses BigQuery's built-in generative AI functions, coupled with remote User Defined Functions (UDFs) that interface with </span><a href="https://cloud.google.com/vertex-ai?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Vertex AI</span></a><span style="vertical-align: baseline;"> APIs. The integration elevates the process of data enrichment and analysis, and offers a more streamlined and efficient workflow.</span></p>
+<h3><strong style="vertical-align: baseline;">The power of BigQuery object tables</strong></h3>
+<p><span style="vertical-align: baseline;">In the example below, we focus on a static image use case, however, this same technique could be used for images created using generative AI. The true potential of this architecture lies in its versatility. The use of object tables in BigQuery means this pattern can be adapted to any form of unstructured data, for example images, audio, documents, opening up a world of possibilities for data science and analysis. This flexibility ensures the architecture can evolve with the changing needs and types of data, helping the solution withstand the test of time in the dynamic field of image curation and generation.</span></p>
+<p><span style="vertical-align: baseline;">This architecture shows the integration of structured and unstructured data, utilizing the strengths of both to enhance platform capabilities. BigQuery serves as a central hub, amalgamating user data information (for example: user demographics, images viewed and used, session duration, session frequency), image metadata, and queries. Concurrently, external AI APIs augment this dataset with insights about the content of the images, for example describing what is happening in a scene (e.g. “a photographic image of a dog playing with a ball on grass”) . </span></p>
+<p><span style="vertical-align: baseline;">This convergence of data facilitates the training of sophisticated image-generation models, tailored to meet the specific requirements of the platform's users. It also unlocks advanced search and image-curation functionalities, enabling users to navigate through an extensive collection of images. The project's ability to provide access to external systems and empower data augmentation within BigQuery helps to centralize analytic workloads. This not only streamlines data analysis but also fosters informed decision-making.</span></p>
+<h3><strong style="vertical-align: baseline;">Solution overview</strong></h3></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/1_-_Model_Analytics.max-1000x1000.png"
+
+ alt="1 - Model Analytics">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">The goal of the solution is to create a way to interact with unstructured data through BigQuery. Using BigQuery object tables to analyze unstructured data in Cloud Storage, you can perform analyses using generative AI models via remote functions, cloud APIs via Vertex AI, or perform inference by using BigQuery ML, and then join the results of these operations with the rest of your structured data in BigQuery.</span></p>
+<h3><strong style="vertical-align: baseline;">Step 1. Creating an example dataset</strong></h3>
+<p><strong style="vertical-align: baseline;">Prerequisites<br/></strong><span style="vertical-align: baseline;">Data: Multiple image repositories on third-party sites like Kaggle and Hugging Face<br/></span><span style="vertical-align: baseline;">Project setup: To get started we need to activating essential project APIs:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">gcloud services enable cloudfunctions.googleapis.com</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">gcloud services enable cloudbuild.googleapis.com</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">gcloud services enable bigqueryconnection.googleapis.com</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">gcloud services enable </span><a href="http://vision.googleapis.com" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">vision.googleapis.com</span></a></p>
+</li>
+</ul>
+<h3><strong style="vertical-align: baseline;">Step 2. Create the object table</strong></h3>
+<p><span style="vertical-align: baseline;">The object table provides the reference to the non-structured data (e.g., audio, live images and images). </span></p>
+<p><span style="vertical-align: baseline;">To do this, we create the BigQuery BigLake remote connection, building a bridge between BigQuery and Cloud Storage:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Command for creation: </span><span style="vertical-align: baseline;">bq mk --connection --location=us-central1 \</span><span style="vertical-align: baseline;"> </span><span style="vertical-align: baseline;">--project_id=bq-object-tables-demo \</span><span style="vertical-align: baseline;"> </span><span style="vertical-align: baseline;">--connection_type=CLOUD_RESOURCE biglake-connection</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">To show the details of this new creation, use: </span><span style="vertical-align: baseline;">bq show --connection bq-object-tables-demo.us-central1.biglake-connection</span></p>
+</li>
+</ul>
+<p><span style="vertical-align: baseline;">Then, give your BQ service account the correct permissions to access your Cloud Storage bucket.</span></p>
+<p><span style="vertical-align: baseline;">Your </span><span style="vertical-align: baseline;">serviceAccountId</span><span style="vertical-align: baseline;"> typically looks like this: </span><span style="vertical-align: baseline;">{"serviceAccountId": "bqcx-012345678910-abcd@gcp-sa-bigquery-condel.iam.gserviceaccount.com"</span><span style="vertical-align: baseline;">}`. And it needs the object viewer permission. This can be achieved by:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'gsutil iam ch \\ serviceAccount:bqcx-012345678910-abcd@gcp-sa-bigquery-condel.iam.gserviceaccount.com:objectViewer gs://bq-object-tables-demo-data'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc2da5a30>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Make your object table in BigQuery in an existing dataset, or create a dataset for your object table.</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Create the dataset with: </span><span style="vertical-align: baseline;">bq mk -d --data_location=us-central1 bq_object_table_demo-dataset</span></p>
+</li>
+</ul>
+<p><span style="vertical-align: baseline;">This is a sample query you can use to create the object table</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'CREATE OR REPLACE EXTERNAL TABLE `bq-object-tables.bq_ot_dataset.bq_object_tables_external_table` \r\nWITH CONNECTION `bq-object-tables.us-east1.biglake-connection` OPTIONS ( object_metadata="DIRECTORY", uris = [\'gs://bq-object-tables-demo-data/*\' ], max_staleness=INTERVAL 30 MINUTE, metadata_cache_mode="AUTOMATIC");'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc2da5040>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">The max_staleness option lets you manage the trade-off between data freshness and performance by specifying a tolerable level of staleness for the materialized view; this can help improve query response times and reduce costs. By setting an appropriate value, you can achieve consistently high performance while keeping costs under control, even when working with large, frequently changing datasets</span><span style="vertical-align: baseline;">.</span></p>
+<p><strong style="vertical-align: baseline;">Create metadata using Native BQ Functionality</strong></p>
+<p><span style="vertical-align: baseline;">These steps can all be automated into a Directed Acyclic Graph (DAG) for use in an orchestration tool such as </span><a href="https://cloud.google.com/composer"><span style="text-decoration: underline; vertical-align: baseline;">Cloud Composer</span></a><span style="vertical-align: baseline;">.</span></p>
+<h3><strong style="vertical-align: baseline;">Step 3. Reference the model from a native generative AI BQML function</strong></h3>
+<p><span style="vertical-align: baseline;">First create the link back to the model in your BQ dataset like this: </span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', "# Create Model\r\nCREATE OR REPLACE MODEL\r\n`bq-object-tables.bq_ot_dataset.myvisionmodel`\r\nREMOTE WITH CONNECTION `bq-object-tables.us-east1.biglake-connection`\r\nOPTIONS (remote_service_type ='cloud_ai_vision_v1');"), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc2da5460>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><strong style="vertical-align: baseline;">Annotate image</strong></p>
+<p><span style="vertical-align: baseline;">This code parses the images, extracts their contents and outputs a JSON array of words that describe the image and the model’s confidence that the description is correct. This function will then put the description into a table.</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', "# Annotate image\r\nSELECT *\r\nFROM ML.ANNOTATE_IMAGE(\r\n MODEL `mydataset.myvisionmodel`,\r\n TABLE `mydataset.mytable`,\r\n STRUCT(['label_detection'] AS vision_features)\r\n);"), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc2da5d30>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><h3><strong style="vertical-align: baseline;">Step 4. Create a UDF in BigQuery</strong></h3>
+<p><span style="vertical-align: baseline;">You can create a Cloud function using </span><a href="https://gist.github.com/hselbie/fde69b900c4c719656ab42cdfb897b88" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">this basic code</span></a><span style="vertical-align: baseline;">. </span></p>
+<p><span style="vertical-align: baseline;">If you’re unsure how to create a cloud function, please see the docs for how to </span><a href="https://cloud.google.com/blog/products/data-analytics/extending-bigquery-functions"><span style="text-decoration: underline; vertical-align: baseline;">create a cloud function UDF</span></a><span style="vertical-align: baseline;">.</span></p>
+<p><span style="vertical-align: baseline;">Then, to deploy the Cloud Function, follow these steps:</span></p>
+<p><span style="vertical-align: baseline;">4.1. </span><a href="https://cloud.google.com/functions/docs/deploying"><span style="text-decoration: underline; vertical-align: baseline;">Deploy your Cloud Function</span></a></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">You may need to enable Cloud Functions API.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">You may need to enable Cloud Build APIs.</span></p>
+</li>
+</ul>
+<p><span style="vertical-align: baseline;">4.2. </span><a href="https://cloud.google.com/bigquery/docs/reference/standard-sql/remote-functions#grant_permission_on_function"><span style="text-decoration: underline; vertical-align: baseline;">Grant the BigQuery connection service account access to the Cloud Function</span></a></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">One way you can find the service account is by using the BigQuery cli ‘show’ command</span></p>
+</li>
+</ul>
+<p><span style="vertical-align: baseline;">4.3. Reference the functions in BigQuery</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Create a BigQuery remote function to reference the Cloud Function UDF</span></p>
+</li>
+</ul></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', "CREATE OR REPLACE FUNCTION `mydataset.vision_safe_search`(signed_url_ STRING) RETURNS JSON\r\nREMOTE WITH CONNECTION `us.gcs-connection`\r\nOPTIONS(endpoint='https://region-myproject.cloudfunctions.net/vision_safe_search',\r\nmax_batching_rows = 1);"), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc2da5190>)])]></dd>
+</dl></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', "CREATE OR REPLACE FUNCTION `mydataset.vision_annotation`(signed_url_ STRING) RETURNS JSON\r\nREMOTE WITH CONNECTION `us.gcs-connection`\r\nOPTIONS(endpoint='https://region-myproject.cloudfunctions.net/vision_annotation',\r\nmax_batching_rows = 1);"), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc2da5a00>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><h3><span style="vertical-align: baseline;">Step 5. Use the function in a query </span></h3></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'CREATE TABLE `mydataset.mid_processing` AS\r\nSELECT uri,mydataset.vision_safe_search(signed_url) as safe_search, mydataset.vision_annotation(signed_url) as annotation\r\nFROM EXTERNAL_OBJECT_TRANSFORM(\r\nTABLE `mydataset.imageall`,\r\n["SIGNED_URL"]);'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc2da59a0>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><h3><strong style="vertical-align: baseline;">Tap into unstructured data with BigQuery object tables and AI</strong></h3>
+<p><span style="vertical-align: baseline;">This architecture demonstrates the power of streamlining data integration for centralized analyses through BigQuery. Although we reference image data for this example, this methodology is highly flexible; using object tables we can reference any type of unstructured data in Cloud Storage buckets that could also refer to audio files that might reference a call center AI use case, for example, or live image files relevant to training a computer vision model. </span></p>
+<p><span style="vertical-align: baseline;">By centralizing data in Cloud Storage and BigQuery and intelligently using object tables, you can efficiently manage both structured and unstructured data. For our image-based example, this unified approach provides a rich dataset that contains user IDs, original prompts, prompt categories, image safety ratings, and even additional ML-generated prompts. </span></p>
+<p><span style="vertical-align: baseline;">The potential applications for these metadata sets are huge. Product teams could use them to build more robust image-generation models or create an advanced image-search system, providing highly relevant results aligned with users' search terms and image descriptions. </span></p>
+<h3><strong style="vertical-align: baseline;">Take the next step</strong></h3>
+<p><span style="vertical-align: baseline;">You can get started today using this framework. For additional help, ask your Google Cloud account manager to reach out to the</span><strong style="vertical-align: baseline;"> </strong><a href="https://cloud.google.com/solutions/data-cloud-isvs?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Built with BigQuery</span><strong style="text-decoration: underline; vertical-align: baseline;"> </strong><span style="text-decoration: underline; vertical-align: baseline;">team</span></a><strong style="vertical-align: baseline;">.</strong><span style="vertical-align: baseline;"> </span></p>
+<p><span style="vertical-align: baseline;">The Built with BigQuery team helps Independent Software Vendors (ISVs) and data providers build innovative applications with </span><a href="https://cloud.google.com/data-cloud?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Google Data Cloud</span></a><span style="vertical-align: baseline;">. Participating companies can: </span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Accelerate product design and architecture through access to designated experts who can provide insight into key use cases, architectural patterns, and best practices</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Amplify success with joint marketing programs to drive awareness, generate demand, and increase adoption</span></p>
+</li>
+</ul></div>Tue, 07 May 2024 16:00:00 +0000https://cloud.google.com/blog/products/data-analytics/perform-product-analysis-with-generative-ai-and-bigquery/PartnersAI & Machine LearningDevelopers & PractitionersData AnalyticsarticleProduct analytics for generative AI model and media asset companies using BigQueryGooglehttps://cloud.google.com/blog/products/data-analytics/perform-product-analysis-with-generative-ai-and-bigquery/Annie XuSr. Customer Engineer, Analytics, Google CloudHugo SelbieCustomer & Partner Solutions Engineer, Gen AI, Google CloudWhat’s new with Active Assist: New Hub UI and four new recommendationshttps://cloud.google.com/blog/products/management-tools/active-assist-gets-new-hub-and-recommendations/<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">The </span><a href="https://cloud.google.com/solutions/active-assist"><span style="text-decoration: underline; vertical-align: baseline;">Active Assist</span></a><span style="vertical-align: baseline;"> portfolio of intelligent tools can help you reduce costs, increase performance, improve security, and even help you make more sustainable decisions. Today, we’re excited to announce some new Active Assist features that address some of our customers’ largest concerns. These features unlock some key functionality that help you better understand and use recommendations, all aimed to help make managing and optimizing your cloud simpler and easier. </span></p>
+<h3><strong style="vertical-align: baseline;">Revamped Recommendation Hub</strong></h3>
+<p><a href="https://console.cloud.google.com/home/recommendations"><span style="text-decoration: underline; vertical-align: baseline;">Recommendation Hub</span></a><span style="vertical-align: baseline;"> is a centralized page on Google Cloud that helps you view all of your recommendations in one place across multiple categories: cost, security, performance, reliability, manageability, and even sustainability. We recently made improvements to help you better understand the recommendations you have and to help you focus on the ones that are the most impactful: </span></p>
+<p role="presentation"><strong style="vertical-align: baseline;">1. Organization-view of recommendations<br/></strong><span style="vertical-align: baseline;">One of our most in-demand features: you can now view all recommendations across all of your projects in your organization in one UI! Simply change the picker at the top left of the screen to choose an organization, and Active Assist shows all the recommendations under your organization (as long as you have the correct IAM permissions).</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/original_images/hubble-1.gif"
+
+ alt="hubble-1">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p role="presentation"><strong style="vertical-align: baseline;">2. Pre-filtered recommendations by value category<br/></strong><span style="vertical-align: baseline;">You can now view all of your recommendations under one category in a simple </span><span style="vertical-align: baseline;">table view, so you can prioritize and focus on the recommendations that are the most </span><span style="vertical-align: baseline;">relevant and important to you.</span></p>
+<p role="presentation"><strong style="vertical-align: baseline;">3. Custom sorting and filtering<br/></strong><span style="vertical-align: baseline;">With our new table views, you can sort and filter by different fields, such as product category, recommendation, cost savings, priority, etc. so you can find and view recommendations more easily. </span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/original_images/hubble-2.gif"
+
+ alt="hubble-2">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><h3><strong style="vertical-align: baseline;">Four new recommendations</strong></h3>
+<p><span style="vertical-align: baseline;">We’re continually adding new recommendations to the Active Assist portfolio based on customer feedback, to help you manage risk and optimize operations. </span></p>
+<p role="presentation"><strong style="vertical-align: baseline;">1. Cloud deprecation and breaking change recommendations<br/></strong><span style="vertical-align: baseline;">At Google Cloud we take pains to provide backwards compatibility for our services. However, from time to time, we need to evolve the platform in a way that could impact some users e.g., for security purposes. In addition to following a stringent process to minimize customer impact, Active Assist now includes recommendations about potential breaking changes, providing an additional mechanism for customers to learn about them.</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/hub-3.max-1000x1000.png"
+
+ alt="hub-3">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Our new </span><a href="https://cloud.google.com/recommender/docs/deprecation-change-recommender"><span style="text-decoration: underline; vertical-align: baseline;">cloud deprecation and breaking changes recommender</span></a><span style="vertical-align: baseline;"> helps identify Cloud resources that will be affected by upcoming deprecations and breaking changes while providing guidelines on how to manage them. Like our other recommendations, you can view them through our </span><a href="https://console.cloud.google.com/home/recommendations"><span style="text-decoration: underline; vertical-align: baseline;">Recommendation Hub UI</span></a><span style="vertical-align: baseline;">, API, and BigQuery export. </span></p>
+<p><span style="vertical-align: baseline;">Deprecation and breaking change recommendations are offered at no charge and are available for all users today. Making sure you get ahead of these changes is important to help prevent any disruptions to your environment and ensure you are on the most reliable and supported services. </span></p>
+<p role="presentation"><strong style="vertical-align: baseline;">2. IAM for BigQuery recommendations<br/></strong><span style="vertical-align: baseline;">We’ve expanded the popular IAM Recommender to include </span><a href="https://cloud.google.com/policy-intelligence/docs/review-apply-role-recommendations-datasets"><span style="text-decoration: underline; vertical-align: baseline;">IAM recommendations on BigQuery datasets</span></a><span style="vertical-align: baseline;">. If your principals have roles on BigQuery datasets but they are not using all of the permissions within that role, you can now receive recommendations to remove or replace any of those roles. These recommendations help you enforce the principle of least privilege by ensuring that principals have only the permissions that they actually need. </span></p>
+<p><span style="vertical-align: baseline;">You can view your recommendations through UI, API, or BigQuery export. The recommendations are currently free but will require Security Command Center Premium after April 29th. </span></p>
+<p role="presentation"><strong style="vertical-align: baseline;">3. Advisory Notifications recommendations<br/></strong><a href="https://cloud.google.com/advisory-notifications/docs/recommendations-overview"><span style="text-decoration: underline; vertical-align: baseline;">Advisory Notifications</span></a><span style="vertical-align: baseline;"> provides IAM policy recommendations to ensure the right parties within your organization have access to view critical security and privacy notifications in the Google Cloud console, so that they can receive and quickly address security notifications. </span></p>
+<p role="presentation"><strong style="vertical-align: baseline;">4. Recent change recommendations<br/></strong><span style="vertical-align: baseline;">We want to help you detect and mitigate issues (e.g., service outages) caused by misconfigurations to your important cloud resources. The new </span><a href="https://cloud.google.com/recommender/docs/recent-change-recommendations"><span style="text-decoration: underline; vertical-align: baseline;">recent change recommendations</span></a><span style="vertical-align: baseline;"> automatically flags recent risky changes to cloud resources that are identified as important based on their usage and other signals. For example, if you deleted a highly used project, recent change recommendations will proactively warn you about the risks associated with the change, helping to identify — and prevent — unintended issues.. </span></p>
+<p><span style="vertical-align: baseline;">We’re excited about these latest </span><a href="https://cloud.google.com/recommender/docs/change-risk-recommendations"><span style="text-decoration: underline; vertical-align: baseline;">change risk recommendations</span></a><span style="vertical-align: baseline;">, and hope they will help you both prevent and mitigate misconfigurations and risky changes to your infrastructure. Try out the new features on </span><a href="https://console.cloud.google.com/home/recommendations"><span style="text-decoration: underline; vertical-align: baseline;">Recommendation Hub</span></a><span style="vertical-align: baseline;"> yourself. If you have any feedback, please feel free to reach out to </span><a href="mailto:active-assist-feedback@google.com"><span style="text-decoration: underline; vertical-align: baseline;">active-assist-feedback@google.com</span></a><span style="vertical-align: baseline;">.</span></p></div>
+<div class="block-related_article_tout">
+
+
+
+
+
+<div class="uni-related-article-tout h-c-page">
+ <section class="h-c-grid">
+ <a href="https://cloud.google.com/blog/products/management-tools/introducing-active-assist-change-risk-recommenders/"
+ data-analytics='{
+ "event": "page interaction",
+ "category": "article lead",
+ "action": "related article - inline",
+ "label": "article: {slug}"
+ }'
+ class="uni-related-article-tout__wrapper h-c-grid__col h-c-grid__col--8 h-c-grid__col-m--6 h-c-grid__col-l--6
+ h-c-grid__col--offset-2 h-c-grid__col-m--offset-3 h-c-grid__col-l--offset-3 uni-click-tracker">
+ <div class="uni-related-article-tout__inner-wrapper">
+ <p class="uni-related-article-tout__eyebrow h-c-eyebrow">Related Article</p>
+
+ <div class="uni-related-article-tout__content-wrapper">
+ <div class="uni-related-article-tout__image-wrapper">
+ <div class="uni-related-article-tout__image" style="background-image: url('')"></div>
+ </div>
+ <div class="uni-related-article-tout__content">
+ <h4 class="uni-related-article-tout__header h-has-bottom-margin">Active Assist change risk recommenders: Introducing a new way to prevent misconfigurations</h4>
+ <p class="uni-related-article-tout__body">Active Assist change risk recommendations help prevent and detect common misconfigurations to help reduce risk, and improve operational r...</p>
+ <div class="cta module-cta h-c-copy uni-related-article-tout__cta muted">
+ <span class="nowrap">Read Article
+ <svg class="icon h-c-icon" role="presentation">
+ <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#mi-arrow-forward"></use>
+ </svg>
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </a>
+ </section>
+</div>
+
+</div>Tue, 07 May 2024 16:00:00 +0000https://cloud.google.com/blog/products/management-tools/active-assist-gets-new-hub-and-recommendations/AI & Machine LearningDatabasesManagement ToolsarticleWhat’s new with Active Assist: New Hub UI and four new recommendationsGooglehttps://cloud.google.com/blog/products/management-tools/active-assist-gets-new-hub-and-recommendations/Sharon FangProduct ManagerRyan IsmertProduct Managerrepareo adopts cloud-based microservices architecture to scale its auto repair businesshttps://cloud.google.com/blog/products/application-modernization/how-repareo-is-modernizing-auto-repair-with-google-cloud/<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">When it comes to auto repair, most of us are at the mercy of our mechanic. We take our car to the local garage, pay for the job, and hope for the best. And with little transparency into the work that has been done, or the costs involved, we can be left feeling unsure whether we got value for money.</span></p>
+<p><span style="vertical-align: baseline;">At </span><a href="https://www.repareo.de/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">repareo</span></a><span style="vertical-align: baseline;">, we are transforming the customer experience of vehicle repair, modernizing the market to make it e-commerce ready, while giving customers full transparency over the car-repair process. Now, they can describe their vehicle problem on our site and immediately receive a list of local garages, including customer reviews, cost breakdowns, and availability, allowing them to make an informed decision about where to take their car. And because our site has direct interfaces with the garages’ booking systems, customers are able to book their preferred garage and appointment directly on our site, saving time calling garages for availability. </span></p>
+<h3><strong style="vertical-align: baseline;">Outgrowing our monolithic architecture</strong></h3>
+<p><span style="vertical-align: baseline;">This year, we will be launching our new infrastructure on Google Cloud. Previously, repareo was built on a monolithic system using a small, hosted server, which was both easy for our small development team to maintain and allowed us to grow the business in a cost-efficient way. However, as we added more features and services, our monolith grew, which had an impact on our development speed, creating a bottleneck for the rest of our application. </span></p>
+<p><span style="vertical-align: baseline;">Reliability became an issue too. repareo is integrated with car management fleets and leasing companies, and many drivers access our services through their car leasing app, making us highly dependent on third-party APIs to function effectively. As we grew, the increase in traffic resulted in these APIs becoming sluggish. During periods of peak traffic, such as the German tire-change season, we would see a 300% surge in traffic, placing a significant strain on our server, which was unable to scale effectively, causing our services to grind to a halt. </span></p>
+<h3><strong style="vertical-align: baseline;">Modernizing infrastructure to modernize the market</strong></h3>
+<p><span style="vertical-align: baseline;">The turning point came last year, when we signed a major deal with a leading global e-commerce player to integrate with its vehicle parts marketplace, enabling customers to book an installation during the checkout process. Realizing that we would need our infrastructure to be able to handle an expected tenfold increase in demand, while conforming with our new service-level agreements (SLAs), we decided it was time to move to the cloud. </span></p>
+<p><span style="vertical-align: baseline;">We knew that a migration would bring other benefits too, enabling us to build a microservices architecture to develop services in modules, as well as allowing us to place certain workloads close to a leading global eCommerce player in vehicle parts in California, for fast response times. As we looked at cloud providers, Google Cloud stood out for the range of technologies and services it offered, with </span><a href="https://cloud.google.com/bigquery?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">BigQuery</span></a><span style="vertical-align: baseline;"> and </span><a href="https://cloud.google.com/apigee?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Apigee</span></a><span style="vertical-align: baseline;"> particularly impressing us as uniquely advanced solutions in the market. </span></p>
+<p><span style="vertical-align: baseline;">Beyond the technology, however, we were just as impressed with Google Cloud’s deep understanding of our industry and its business network within the automotive sector, as well as by the personal relationship we quickly built with the Google Cloud team. Migrating to a new provider is a once-in-a-lifetime decision, a marriage of sorts, and with Google Cloud the relationship immediately felt like it was built to last. </span></p>
+<h3><strong style="vertical-align: baseline;">A robust, reliable system for a smoother customer experience</strong></h3>
+<p><span style="vertical-align: baseline;">We’re currently halfway through our migration, which has proved to be a steep learning curve for us, given the scale of the undertaking for our small team of developers. However, Apigee has helped to make the migration smooth by enabling us to easily set up a staging environment to test and adjust our system before going live, with no impact on our users. </span></p>
+<p><span style="vertical-align: baseline;">We expect to have completed the migration in less than six months in total. Once live, we will have a robust, scalable system, capable of meeting the needs of a significantly larger user base. Building and managing our APIs with Apigee means we will be able to use the caching system to cache the high number of API requests on the site, allowing us to offer high-performance buffering algorithms without having to drastically increase the scale of the underlying system. And because Apigee’s logging system is so well developed, we will easily be able to spot and remedy any integration issues, to ensure our APIs function effectively. As a result, our customers will enjoy a smooth, reliable booking system and real-time repair updates, while garages will benefit from far wider reach. </span></p>
+<p><span style="vertical-align: baseline;">We won’t need to worry about being able to handle fluctuations in demand either, as the autoscale feature of </span><a href="https://cloud.google.com/kubernetes-engine?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Google Kubernetes Engine</span></a><span style="vertical-align: baseline;"> (GKE) will automatically scale up our workloads to meet surges in traffic and scale down again during quiet periods to help ensure we aren’t using more compute than necessary. This cost-efficient provisioning means we will no longer have to worry about the ability of our system to handle periods of peak traffic, with our customers benefiting from a fast, reliable service. </span></p>
+<h3><strong style="vertical-align: baseline;">Taking our developers up a gear with easy-to-use, managed services</strong></h3>
+<p><span style="vertical-align: baseline;">Our development efficiency has already significantly improved, thanks to the built-in features and managed services of Google Cloud. Apigee, for example, has a built-in key management system to enable APIs to communicate securely, which means our development team doesn’t need to spend time and money building our own system. Similarly, the fact that </span><a href="https://cloud.google.com/sql?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Cloud SQL</span></a><span style="vertical-align: baseline;"> is a managed database means we don’t need to spend time updating and maintaining it. GKE, meanwhile, improves our developer efficiency thanks to its easy integration with automation tools, increasing our deployment speed by at least 15%.</span></p>
+<p><span style="vertical-align: baseline;">All of this means that our developers are free to focus on the core business logic and developing new features, such as new RPA-based technology to gather appointment availability from garage websites, which we were able to build and release inside a week, where it would have taken a month using the old infrastructure.</span></p>
+<h3><strong style="vertical-align: baseline;">A firm foundation for sustained growth</strong></h3>
+<p><span style="vertical-align: baseline;">With a number of other significant deals in the pipeline, repareo is now entering a period of sustained growth as we rapidly increase our customer base and prepare to enter new markets. That level of scaling simply wouldn’t be possible without Google Cloud, with its global network and regional data centers making it easy to move into any new region and enjoy rapid response times. While its scalable architecture means we can be confident that our infrastructure will always be able to scale with us.</span></p>
+<p><span style="vertical-align: baseline;">As we continue our mission to make auto repair more transparent and convenient for more people, we are confident that with Google Cloud we have the right provider to help move our business into the fast lane.</span></p></div>Tue, 07 May 2024 08:00:00 +0000https://cloud.google.com/blog/products/application-modernization/how-repareo-is-modernizing-auto-repair-with-google-cloud/Infrastructure ModernizationCustomersApplication Modernizationarticlerepareo adopts cloud-based microservices architecture to scale its auto repair businesshttps://storage.googleapis.com/gweb-cloudblog-publish/images/image_30.max-600x600.jpgGooglehttps://cloud.google.com/blog/products/application-modernization/how-repareo-is-modernizing-auto-repair-with-google-cloud/Philipp HaacCEO, repareoTobias ReisnerCTO & Co-Founder, repareoMaintain business continuity across regions with BigQuery managed disaster recoveryhttps://cloud.google.com/blog/products/data-analytics/bigquery-gets-managed-disaster-recovery/<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Geographical redundancy is a fundamental part of building a resilient cloud-based data strategy. For many years, BigQuery has offered an industry-leading 99.99% </span><a href="https://cloud.google.com/bigquery/sla"><span style="text-decoration: underline; vertical-align: baseline;">uptime service-level agreement</span></a><span style="vertical-align: baseline;"> (SLA) for availability within a single geographical region. Full redundancy across two data centers within a single region is included with every BigQuery dataset you create and is managed in a completely transparent manner. </span></p>
+<p><span style="vertical-align: baseline;">For customers looking for enhanced redundancy across large geographic regions, we are now introducing </span><strong style="vertical-align: baseline;">managed disaster recovery</strong><span style="vertical-align: baseline;"> for BigQuery. This feature, now in preview, offers automated failover of compute and storage and a new cross-regional SLA tailored for business-critical workloads. This feature enables you to ensure business continuity in the unlikely event of a total regional infrastructure outage. Managed disaster recovery also provides failover configurations for capacity reservations, so you can manage query and storage failover behavior. This feature is available through </span><a href="https://cloud.google.com/bigquery/docs/editions-intro"><span style="text-decoration: underline; vertical-align: baseline;">BigQuery Enterprise Plus edition</span></a><span style="vertical-align: baseline;">.</span></p>
+<h3><strong style="vertical-align: baseline;">How does it work?</strong></h3>
+<p><span style="vertical-align: baseline;">Customers using BigQuery’s enterprise plus edition can now configure their capacity reservations to enable automated failover across distinct geographic regions. Extending the capabilities of BigQuery’s </span><a href="https://cloud.google.com/bigquery/docs/data-replication"><span style="text-decoration: underline; vertical-align: baseline;">cross-region dataset replication</span></a><span style="vertical-align: baseline;">, failover reservations ensure that the location of both data and compute resources are coordinated during a disaster recovery event.</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/original_images/image1_fRF1oyb.png"
+
+ alt="Image 1 - First image on blog">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Slot capacity in the secondary region for enterprise plus edition reservations are provisioned and maintained automatically at </span><span style="font-style: italic; vertical-align: baseline;">no additional cost</span><span style="vertical-align: baseline;">. Some competitive products require customers to duplicate their compute clusters in the secondary location.</span></p>
+<p><span style="vertical-align: baseline;">In the event of a total regional outage, the secondary region can be promoted to the primary role for both compute and data. With BigQuery’s query routing layer, failover is completely transparent to end users and tools.</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Primary region:</strong><span style="vertical-align: baseline;"> The region containing the current primary replica of a </span><a href="https://cloud.google.com/bigquery/docs/datasets-intro"><span style="text-decoration: underline; vertical-align: baseline;">dataset</span></a><span style="vertical-align: baseline;">. This is also the region where the dataset data can be modified (e.g. loads, DDL, or DML).</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Secondary region:</strong><span style="vertical-align: baseline;"> The region where the failover reservation standby capacity and replicated datasets are available in the case of a regional outage.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Failover reservation:</strong><span style="vertical-align: baseline;"> An enterprise plus edition reservation configured with a primary/secondary region pair. Note: Datasets are attached to failover reservations. </span></p>
+</li>
+</ul>
+<p><span style="vertical-align: baseline;">The dataset replica in the primary region is the </span><span style="font-style: italic; vertical-align: baseline;">primary replica</span><span style="vertical-align: baseline;">, and the replica in the secondary region is the </span><span style="font-style: italic; vertical-align: baseline;">secondary replica</span><span style="vertical-align: baseline;">. These roles are swapped during the failover process.</span></p>
+<p><span style="vertical-align: baseline;">The primary replica is writeable, and the secondary replica is read-only. Writes to the primary replica are asynchronously replicated to the secondary replica. Within each region, the data is stored redundantly in two zones. Network traffic never leaves the Google Cloud network.</span></p>
+<h3><strong style="vertical-align: baseline;">What is a region pair? </strong></h3>
+<p><span style="vertical-align: baseline;">A region pair in BigQuery’s managed disaster recovery is a pair of regions that are geographically supported by </span><a href="https://cloud.google.com/storage/docs/availability-durability#turbo-replication"><span style="text-decoration: underline; vertical-align: baseline;">turbo replication</span></a><span style="vertical-align: baseline;"> and compute redundancy. Within the defined region pair, BigQuery replicates data between the two regions and manages secondary available capacity. This replication allows BigQuery managed disaster recovery to provide high availability and durability for data. Customers are able to define their desired region pair (based on the supported regions) per failover reservation. </span></p>
+<h3><strong style="vertical-align: baseline;">Supported region pairs</strong></h3>
+<p><span style="vertical-align: baseline;">BigQuery’s managed disaster recovery feature supports failover reservations across specific region pairs (</span><a href="https://cloud.google.com/storage/docs/locations#location-dr"><span style="text-decoration: underline; vertical-align: baseline;">similar to Cloud Storage, for regions within a geographic area</span></a><span style="vertical-align: baseline;">). You can designate either region in a pair for your initial primary or secondary region.</span></p>
+<h2><strong style="vertical-align: baseline;">Capacity in the secondary region</strong></h2>
+<p><span style="vertical-align: baseline;">BigQuery ensures that the capacity of your primary region will be available in your secondary region within five minutes of a failover. This assurance applies to your reservation baseline, whether it’s used or not. BigQuery also provides the same level of </span><a href="https://cloud.google.com/bigquery/docs/slots-autoscaling-intro"><span style="text-decoration: underline; vertical-align: baseline;">autoscaling</span></a><span style="vertical-align: baseline;"> availability as provided in the primary.</span></p>
+<h3><strong style="vertical-align: baseline;">How much does it cost?</strong></h3>
+<p><span style="vertical-align: baseline;">BigQuery's managed disaster recovery feature is available with the </span><a href="https://cloud.google.com/bigquery/docs/editions-intro"><span style="text-decoration: underline; vertical-align: baseline;">Enterprise Plus edition</span></a><span style="vertical-align: baseline;">. Standby compute capacity in the secondary region is included with the per slot-hour price with no requirement to purchase separate standby capacity. As an option, you may choose to provision additional Enterprise Plus reservations in the secondary region, specifically for read-only queries.</span></p>
+<p><span style="vertical-align: baseline;">Managed disaster recovery customers are billed for </span><a href="https://cloud.google.com/bigquery/docs/data-replication"><span style="text-decoration: underline; vertical-align: baseline;">replicated storage</span></a><span style="vertical-align: baseline;"> in the primary and secondary regions for associated datasets. At GA, this feature will automatically use </span><a href="https://cloud.google.com/storage/docs/managing-turbo-replication"><span style="text-decoration: underline; vertical-align: baseline;">turbo replication</span></a><span style="vertical-align: baseline;"> for data transfer between regions. </span></p>
+<p> </p>
+<div align="left">
+<div style="color: #5f6368; overflow-x: auto; overflow-y: hidden; width: 100%;">
+<div style="color: #5f6368; overflow-x: auto; overflow-y: hidden; width: 100%;">
+<div style="color: #5f6368; overflow-x: auto; overflow-y: hidden; width: 100%;">
+<div style="color: #5f6368; overflow-x: auto; overflow-y: hidden; width: 100%;">
+<div style="color: #5f6368; overflow-x: auto; overflow-y: hidden; width: 100%;">
+<div style="color: #5f6368; overflow-x: auto; overflow-y: hidden; width: 100%;">
+<div style="color: #5f6368; overflow-x: auto; overflow-y: hidden; width: 100%;">
+<div style="color: #5f6368; overflow-x: auto; overflow-y: hidden; width: 100%;">
+<div style="color: #5f6368; overflow-x: auto; overflow-y: hidden; width: 100%;">
+<div style="color: #5f6368; overflow-x: auto; overflow-y: hidden; width: 100%;">
+<div style="color: #5f6368; overflow-x: auto; overflow-y: hidden; width: 100%;"><table><colgroup><col/><col/></colgroup>
+<tbody>
+<tr>
+<td style="vertical-align: top; border: 1px solid #000000; padding: 16px;">
+<p><strong style="vertical-align: baseline;">SKU</strong></p>
+</td>
+<td style="vertical-align: top; border: 1px solid #000000; padding: 16px;">
+<p><strong style="vertical-align: baseline;">Billing description</strong></p>
+</td>
+</tr>
+<tr>
+<td style="vertical-align: top; border: 1px solid #000000; padding: 16px;">
+<p><span style="vertical-align: baseline;">Enterprise Plus Edition</span></p>
+</td>
+<td style="vertical-align: top; border: 1px solid #000000; padding: 16px;">
+<p><span style="vertical-align: baseline;">$0.10 / slot-hr (ex. US Pricing)</span></p>
+</td>
+</tr>
+<tr>
+<td style="vertical-align: top; border: 1px solid #000000; padding: 16px;">
+<p><span style="vertical-align: baseline;">Storage</span></p>
+</td>
+<td style="vertical-align: top; border: 1px solid #000000; padding: 16px;">
+<p><span style="vertical-align: baseline;">Storage bytes in the secondary region are billed at the same list price as storage bytes in the primary region. See </span><a href="https://cloud.google.com/bigquery/pricing#storage"><span style="text-decoration: underline; vertical-align: baseline;">BigQuery Storage pricing</span></a><span style="vertical-align: baseline;"> for more information.</span></p>
+</td>
+</tr>
+<tr>
+<td style="vertical-align: top; border: 1px solid #000000; padding: 16px;">
+<p><span style="vertical-align: baseline;">Data transfer</span></p>
+</td>
+<td style="vertical-align: top; border: 1px solid #000000; padding: 16px;">
+<p><span style="vertical-align: baseline;">Managed disaster recovery uses turbo replication*</span></p>
+<p><span style="vertical-align: baseline;">Data transfer used during replication:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">is charged based on physical bytes</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">is charged on a per physical GB replicated basis. </span></p>
+</li>
+</ul>
+<p><span style="vertical-align: baseline;">Note: </span><a href="https://cloud.google.com/storage/pricing#north-america_1"><span style="text-decoration: underline; vertical-align: baseline;">Turbo replication will be 2x pricing of “default replication” </span></a></p>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+</div>
+</div>
+</div>
+</div>
+</div>
+</div>
+</div>
+</div>
+</div>
+<p><strong><span style="vertical-align: baseline;">* </span><span style="vertical-align: baseline;">Turbo replication is not available during preview but will be enabled automatically at general availability (GA).</span></strong></p>
+<h3><strong style="vertical-align: baseline;">Recovery Time Objective (RTO)</strong></h3>
+<p><span style="vertical-align: baseline;">Promotion of a secondary reservation and associated datasets takes less than five minutes, even if the primary region is down. All queries in flight are canceled and rejected during the RTO timeline.</span></p>
+<h3><strong style="vertical-align: baseline;">Recovery Point Objective (RPO)</strong></h3>
+<p><span style="vertical-align: baseline;">Data will be less than 15 minutes old in secondary dataset replicas configured for failover reservation between supported region pairs, turbo replication enabled and only after initial replication is completed (also known as backfill). </span></p>
+<p><strong style="vertical-align: baseline;">Note: Turbo replication and RPO/RPO with SLA are not available during preview.</strong></p>
+<h3><strong style="vertical-align: baseline;">Configuration in action</strong></h3>
+<p><span style="vertical-align: baseline;">During preview, managed disaster recovery configuration is supported via the BigQuery Console (UI) and SQL. The following workflow shows how you can set up and manage disaster recovery in BigQuery:</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/Image_2_-_Second_image_on_blog.max-1000x1000.png"
+
+ alt="Image 2 - Second image on blog">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><strong style="vertical-align: baseline;">Create a replica for a given dataset</strong></p>
+<p><span style="vertical-align: baseline;">To replicate a dataset, use the </span><a href="https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_add_replica_statement"><span style="text-decoration: underline; vertical-align: baseline;">ALTER SCHEMA ADD REPLICA DDL statement</span></a><span style="vertical-align: baseline;">.</span></p>
+<p><span style="vertical-align: baseline;">After you add a replica, it takes time for the initial copy operation to complete. You can still run queries referencing the primary replica while the data is being replicated, with no reduction in query-processing capacity.</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', "-- Create the primary replica in the primary region.\r\nCREATE SCHEMA my_dataset OPTIONS(location='us-west1');\r\n-- Create a replica in the secondary region.\r\nALTER SCHEMA my_dataset\r\nADD REPLICA `us-east1`\r\nOPTIONS(location='us-east1');"), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc4aa93d0>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><strong style="vertical-align: baseline;">Configure a failover reservation + attach a dataset</strong></p>
+<p><span style="vertical-align: baseline;">The first step is to create a failover reservation and specify its secondary location. Specifying a secondary location can also be done for existing Enterprise Plus reservations.</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', "CREATE RESERVATION `project1.region-us-west1.my_failover_reservation` \r\n OPTIONS (slot_capacity = 200, edition = ENTERPRISE_PLUS,\r\n secondary_location='us-east1);"), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc4aa9d30>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">The next step is to associate one or more datasets with the failover reservation. The dataset needs to be replicated in the same primary / secondary region as specified in the reservation.</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'ALTER SCHEMA `my_dataset`\r\n SET OPTIONS (failover_reservation = \r\n `project1.my_failover_reservation`);'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc4aa9190>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><strong style="vertical-align: baseline;">Promote the failover reservation + dataset in the secondary</strong></p>
+<p><span style="vertical-align: baseline;">Fail over the reservation and associated datasets. This must be performed from the secondary region.</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'ALTER RESERVATION `project1.region-us-east1.my_failover_reservation` \r\n SET OPTIONS (is_primary = true);'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc4aa91c0>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><strong style="vertical-align: baseline;">Fail back to original primary</strong></p>
+<p><span style="vertical-align: baseline;">Fail back the reservation and associated datasets (performed from the new secondary/old primary).</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'ALTER RESERVATION `project1.region-us-west1.my_failover_reservation` \r\n SET OPTIONS (is_primary = true);'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc4aa91f0>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><h3><strong style="vertical-align: baseline;">Getting started</strong></h3>
+<p><span style="vertical-align: baseline;">Business continuity is paramount for customers with mission-critical data environments. We are excited to make the preview of BigQuery’s managed disaster recovery feature available for your testing. You can learn more about managed disaster recovery and how to get started in the BigQuery </span><a href="https://cloud.google.com/bigquery/docs/managed-disaster-recovery"><span style="text-decoration: underline; vertical-align: baseline;">managed disaster recovery QuickStart</span></a><span style="vertical-align: baseline;">. </span></p></div>Mon, 06 May 2024 16:00:00 +0000https://cloud.google.com/blog/products/data-analytics/bigquery-gets-managed-disaster-recovery/Management ToolsData AnalyticsarticleMaintain business continuity across regions with BigQuery managed disaster recoveryGooglehttps://cloud.google.com/blog/products/data-analytics/bigquery-gets-managed-disaster-recovery/Larry HendersonProduct ManagerBrian WelckerDirector, Product ManagementAdvancing the art of AI-driven security with Google Cloudhttps://cloud.google.com/blog/products/identity-security/advancing-the-art-of-ai-driven-security-with-google-cloud-at-rsa/<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">The advent of generative AI has unlocked new opportunities to empower defenders and security professionals. We have already seen how AI can transform malware analysis at scale as we work to deliver better outcomes for defenders. In fact, using Gemini 1.5 Pro, we were recently able to </span><a href="https://cloud.google.com/blog/topics/threat-intelligence/gemini-for-malware-analysis"><span style="text-decoration: underline; vertical-align: baseline;">reverse engineer and analyze</span></a><span style="vertical-align: baseline;"> the decompiled code of the WannaCry malware in a single pass — and identify the killswitch — in only 34 seconds. </span></p>
+<p><span style="vertical-align: baseline;">Our vision for AI is to accelerate your ability to protect and defend against threats by shifting from manual, time-intensive efforts to assisted and, ultimately, </span><a href="https://inthecloud.withgoogle.com/security-product-vision-ai-security/download.html" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">semi-autonomous security</span></a><span style="vertical-align: baseline;"> — while providing you with curated tools and services to </span><a href="https://services.google.com/fh/files/misc/best-practices-for-securely-deploying-ai-on-google-cloud.pdf" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">secure your AI data, models, applications, and infrastructure</span></a><span style="vertical-align: baseline;">. We do this by empowering defenders with Gemini in Security, which uses SecLM, our security-tuned API, as well as providing tools and services to manage AI risk to your environment. Our Mandiant experts are able to help you secure your AI journey wherever you are.</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/1_CbJIeSS.max-1000x1000.png"
+
+ alt="1">
+
+ </a>
+
+ <figcaption class="article-image__caption "><p data-block-key="5bgn0">Managing AI risk and empowering defenders with gen AI.</p></figcaption>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Today at the RSA Conference in San Francisco, we’re sharing more on our vision for the intersection between AI and cybersecurity, including how we help organizations secure AI systems and provide AI tools to support defenders. We are introducing new AI offerings from Mandiant Consulting and new features in Security Command Center Enterprise to help address security challenges when adopting AI. We are also announcing the general availability of Gemini across several security offerings including </span><a href="https://cloud.google.com/blog/products/identity-security/introducing-google-threat-intelligence-actionable-threat-intelligence-at-google-scale-at-rsa"><span style="text-decoration: underline; vertical-align: baseline;">Google Threat Intelligence</span></a><span style="vertical-align: baseline;"> and </span><a href="https://cloud.google.com/blog/products/identity-security/introducing-google-security-operations-intel-driven-ai-powered-secops-at-rsa"><span style="text-decoration: underline; vertical-align: baseline;">Google Security Operations</span></a><span style="vertical-align: baseline;"> to further empower defenders with generative AI.</span></p>
+<h3><strong style="vertical-align: baseline;">New services leverage security and AI expertise from Google</strong></h3>
+<p><span style="vertical-align: baseline;">As customers integrate AI into every area of their business, they tell us that securing their use of AI is essential. The recent </span><a href="https://services.google.com/fh/files/misc/csa_state_of_ai_and_security_survey_google_cloud.pdf" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">State of AI and Security Survey Report</span></a><span style="vertical-align: baseline;"> from the </span><a href="https://cloudsecurityalliance.org/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Cloud Security Alliance</span></a><span style="vertical-align: baseline;"> highlighted that while many professionals are confident in their organization’s ability to protect AI systems, there is still a significant portion that recognize the risks of underestimating threats. </span></p>
+<p><span style="vertical-align: baseline;">Our </span><a href="https://safety.google/cybersecurity-advancements/saif/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Secure AI Framework</span></a><span style="vertical-align: baseline;"> (SAIF) provides a taxonomy of risks associated with AI workloads and recommended mitigations. Today we are announcing new offerings from </span><a href="http://cloud.google.com/security/solutions/mandiant-ai-consulting"><span style="text-decoration: underline; vertical-align: baseline;">Mandiant Consulting</span></a><span style="vertical-align: baseline;"> that can help organizations support SAIF and secure the use of AI. Mandiant's AI consulting services can help assess the security of your AI pipelines and test your AI defense and response with </span><a href="https://cloud.google.com/blog/transform/prompt-findings-our-ai-red-teams-first-report-qa"><span style="text-decoration: underline; vertical-align: baseline;">red teaming</span></a><span style="vertical-align: baseline;">. These services can also help your defenders identify and implement ways to use AI to enhance cyber defenses and streamline investigative capabilities. </span></p>
+<p><span style="vertical-align: baseline;">“The use of AI opens up a world of possibilities and enterprises recognize that in order to take advantage of the potential of these innovations, they need to get ahead of new security risks,” said Jurgen Kutscher, vice president, Mandiant Consulting, Google Cloud. “From helping secure training data to assessing AI applications for vulnerabilities, our Mandiant Consulting experts can provide recommendations based on Google’s own experience protecting and deploying AI. We’re excited to bring these new services to market to help our clients leverage AI more securely and transform their operations."</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/original_images/NSS_demo_RSA_2024_small.gif"
+
+ alt="NSS demo RSA 2024 small">
+
+ </a>
+
+ <figcaption class="article-image__caption "><p data-block-key="oojmj">Notebook Security Scanner identifies package vulnerabilities and recommends next steps to remediate individual packages.</p></figcaption>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><h3><strong style="vertical-align: baseline;">Securing AI workloads against risks</strong></h3>
+<p><span style="vertical-align: baseline;">We are also announcing new AI-protection capabilities that can help our customers implement SAIF by building on our release of </span><a href="https://cloud.google.com/blog/products/identity-security/introducing-security-command-center-enterprise"><span style="text-decoration: underline; vertical-align: baseline;">Security Command Center Enterprise</span></a><span style="vertical-align: baseline;"> — our cloud risk-management solution that fuses cloud security and enterprise security operations: </span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Notebook Security Scanner</strong><span style="vertical-align: baseline;">, now available in preview, detects and provides remediation advice for vulnerabilities introduced by open-source software installed in managed notebooks.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Model Armor</strong><span style="vertical-align: baseline;">, expected to be in preview in Q3, can</span><strong style="vertical-align: baseline;"> </strong><span style="vertical-align: baseline;">enable customers to inspect, route, and protect foundation model prompts and responses. It can help customers </span><a href="https://cloud.google.com/transform/5-gen-ai-security-terms-busy-business-leaders-should-know"><span style="text-decoration: underline; vertical-align: baseline;">mitigate risks</span></a><span style="vertical-align: baseline;"> such as prompt injections, jailbreaks, toxic content, and sensitive data leakage. Model Armor will integrate with products across Google Cloud, including Vertex AI. </span></p>
+</li>
+</ul>
+<p><span style="vertical-align: baseline;">If you’d like to learn more about early access for Model Armor, you can</span><span style="vertical-align: baseline;"> </span><a href="https://forms.gle/egcAxwmyaQzaeZH4A" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">sign up here</span></a><span style="vertical-align: baseline;">.</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/original_images/3_Sfm220W.gif"
+
+ alt="3">
+
+ </a>
+
+ <figcaption class="article-image__caption "><p data-block-key="thm68">Model Armor allows users to configure policies and set content safety filters to help block or redact inappropriate model prompts and responses.</p></figcaption>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><h3><span style="vertical-align: baseline;">Empowering defenders with new gen AI security tools</span></h3>
+<p><span style="vertical-align: baseline;">Today, we’ve also shared how security teams can better defend against threats with </span><a href="https://cloud.google.com/security/products/security-operations"><span style="text-decoration: underline; vertical-align: baseline;">Google Security Operations</span></a><span style="vertical-align: baseline;">, our AI-powered platform to help empower SOC teams to more easily detect and respond to threats. Gemini in Security Operations now includes a new assisted investigation feature that navigates users through the platform based on the context of an investigation. It can help hunt for the latest threats with vital information from Google Threat Intelligence and MITRE, analyze security events, create detections using natural language, and recommend next steps to take. </span></p>
+<p><span style="vertical-align: baseline;">Users can also ask Gemini to create a response playbook using natural language, which can simplify the time-consuming task of manually constructing one. The user can further refine the generated playbook and simulate its execution. These new enhancements can give security teams a boost across the detection and response lifecycle. </span></p>
+<p><span style="vertical-align: baseline;">“Gemini in Security Operations is enabling us to enhance the efficiency of our Cybersecurity Operations Center program as we continue to drive operational excellence,” said Ronald Smalley, senior vice president, cybersecurity operations, Fiserv. “Detection engineers can create detections and playbooks with less effort, and security analysts can find answers quickly with intelligent summarization and natural language search. This is critical as SOC teams continue to manage increasing data volumes and need to detect, validate, and respond to events faster.“</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/original_images/4_Mtsip4A.gif"
+
+ alt="4">
+
+ </a>
+
+ <figcaption class="article-image__caption "><p data-block-key="thm68">Gemini in Security Operations aids investigations and helps users easily create rules for detections.</p></figcaption>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">We also are introducing </span><a href="https://cloud.google.com/security/products/threat-intelligence/?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Google Threat Intelligence</span></a><span style="vertical-align: baseline;">, a new offering that can help you reduce the time it takes to identify and protect against novel threats by bringing together investigative learnings from Mandiant frontline experts, the VirusTotal intel community, and Google threat insights from protecting billions of devices and user accounts. </span></p>
+<p><span style="vertical-align: baseline;">With Gemini in Threat Intelligence, analysts can now conversationally search Mandiant’s vast frontline research to understand threat actor behaviors in seconds, and read AI-powered summaries of relevant open-source intelligence (OSINT) articles the platform automatically ingests to help reduce investigation time. </span></p>
+<p><span style="vertical-align: baseline;">“Our main objective is to understand the purpose of the threat actor. The AI summaries provided by Gemini in Threat Intelligence make it easy to get an overview of the actor, information about relevant entities, and which regions they're targeting,” said the director of information security at a leading multinational professional services organization. “The information flows really smoothly and helps us gather the intelligence we need in a fraction of the time."</span></p>
+<p><span style="vertical-align: baseline;">Plus, Gemini in Threat Intelligence includes </span><a href="https://blog.virustotal.com/2024/01/uncovering-hidden-threats-with.html" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Code Insight</span></a><span style="vertical-align: baseline;">, which can inspect more than 200 file types, summarize their unique properties, and identify potentially malicious code. Gemini makes it easier for security professionals to understand the threats that matter most to their organization and take action to respond.</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/original_images/5_qBjrMG1.gif"
+
+ alt="5">
+
+ </a>
+
+ <figcaption class="article-image__caption "><p data-block-key="thm68">Gemini in Google Threat Intelligence allows users to conversationally search Mandiant’s vast corpus of frontline research.</p></figcaption>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><h3><strong style="vertical-align: baseline;">Make Google part of your security team</strong></h3>
+<p><span style="vertical-align: baseline;">With rapid advances in AI technology, the line of what is possible is a moving target. We have a </span><a href="https://inthecloud.withgoogle.com/security-product-vision-ai-security/download.html" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">vision</span></a><span style="vertical-align: baseline;"> </span><span style="vertical-align: baseline;">for a world in which the practice of “doing security” is less laborious and more durable, as AI offloads routine tasks and frees the experts to focus on the most complex issues. </span></p>
+<p><span style="vertical-align: baseline;">Organizations can now address security challenges with the same capabilities that Google uses to keep more people and organizations safe online than anyone else in the world</span></p>
+<p><span style="vertical-align: baseline;">To learn more about AI and security, and the rest of Google Cloud Security’s co</span><span style="vertical-align: baseline;">mprehensive portfolio</span><span style="vertical-align: baseline;">, come meet us in person at our </span><a href="https://www.rsaconference.com/usa/expo-and-sponsors/sponsor-details/google-cloud%20security-1690826518852001xqzp" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">RSA Conference booth</span></a><span style="vertical-align: baseline;"> (N5644). You can also catch us at our RSA Conference </span><a href="https://cloud.google.com/blog/products/identity-security/your-insiders-guide-to-google-cloud-security-at-rsa-conference-2024"><span style="text-decoration: underline; vertical-align: baseline;">keynotes, presentations, and meetups</span></a><span style="vertical-align: baseline;">, and get the latest </span><a href="http://cloud.google.com/security/ai"><span style="text-decoration: underline; vertical-align: baseline;">AI and Security updates here</span></a><span style="vertical-align: baseline;">.</span></p></div>Mon, 06 May 2024 13:00:00 +0000https://cloud.google.com/blog/products/identity-security/advancing-the-art-of-ai-driven-security-with-google-cloud-at-rsa/Security & IdentityarticleAdvancing the art of AI-driven security with Google Cloudhttps://storage.googleapis.com/gweb-cloudblog-publish/images/AI-driven_security.max-600x600.jpgGooglehttps://cloud.google.com/blog/products/identity-security/advancing-the-art-of-ai-driven-security-with-google-cloud-at-rsa/Steph HaySenior Director, Google Cloud SecurityUmesh ShankarChief Technologist, Google Cloud SecurityIntroducing Google Security Operations: Intel-driven, AI-powered SecOpshttps://cloud.google.com/blog/products/identity-security/introducing-google-security-operations-intel-driven-ai-powered-secops-at-rsa/<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">In the generative AI-era, security teams are looking for a fully-operational, high-performing security operations solution that can drive productivity while empowering defenders to detect and mitigate new threats.</span></p>
+<p><span style="vertical-align: baseline;">Today at the RSA Conference in San Francisco, we’re announcing </span><a href="https://cloud.google.com/blog/products/identity-security/advancing-the-art-of-ai-driven-security-with-google-cloud-at-rsa"><span style="text-decoration: underline; vertical-align: baseline;">AI innovations across the Google Cloud Security portfolio</span></a><span style="vertical-align: baseline;">, including </span><a href="https://cloud.google.com/blog/products/identity-security/introducing-google-threat-intelligence-actionable-threat-intelligence-at-google-scale-at-rsa"><span style="text-decoration: underline; vertical-align: baseline;">Google Threat Intelligence</span></a><span style="vertical-align: baseline;">, and the latest release of Google Security Operations. </span><span style="vertical-align: baseline;">Today’s update is designed help to reduce the do-it-yourself complexity of SecOps and enhance the productivity of your entire Security Operations Center.</span></p></div>
+<div class="block-video">
+
+
+
+<div class="article-module article-video ">
+ <figure>
+ <a class="h-c-video h-c-video--marquee"
+ href="https://youtube.com/watch?v=R1zObTV2oZo"
+ data-glue-modal-trigger="uni-modal-R1zObTV2oZo-"
+ data-glue-modal-disabled-on-mobile="true">
+
+
+
+
+ <div class="article-video__aspect-image"
+ style="background-image: url(https://storage.googleapis.com/gweb-cloudblog-publish/images/1_-_Google_Cloud_YouTube__Brand_Anthem.max-1000x1000.jpg);">
+ <span class="h-u-visually-hidden">Introducing Google Security Operations</span>
+ </div>
+
+ <svg role="img" class="h-c-video__play h-c-icon h-c-icon--color-white">
+ <use xlink:href="#mi-youtube-icon"></use>
+ </svg>
+ </a>
+
+
+ </figure>
+</div>
+
+<div class="h-c-modal--video"
+ data-glue-modal="uni-modal-R1zObTV2oZo-"
+ data-glue-modal-close-label="Close Dialog">
+ <a class="glue-yt-video"
+ data-glue-yt-video-autoplay="true"
+ data-glue-yt-video-height="99%"
+ data-glue-yt-video-vid="R1zObTV2oZo"
+ data-glue-yt-video-width="100%"
+ href="https://youtube.com/watch?v=R1zObTV2oZo"
+ ng-cloak>
+ </a>
+</div>
+
+</div>
+<div class="block-paragraph_advanced"><h3><strong style="vertical-align: baseline;">Turn intelligence into action</strong></h3>
+<p><span style="vertical-align: baseline;">At </span><a href="https://cloud.withgoogle.com/next/session-library?filters=track-security-professionals#all" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Next ‘24</span></a><span style="vertical-align: baseline;">, we shared how Applied Threat Intelligence can help teams turn intelligence into action, uncover more threats with less effort, and unlock deeper threat hunting and investigation workflows. Today we are unveiling new features that will use AI to automatically generate detections based on new threat discoveries. Coming later this year, this new capability will help enable you to identify malicious activity operating in your environment, and share clear directions that guide you through triage and response. </span></p>
+<p><span style="vertical-align: baseline;">“Google Security Operations provides access to unique threat intelligence and advanced capabilities that are highly integrated into the platform. It enables security teams to surface the latest threats in a turnkey way that doesn’t require complicated engineering,” said Michelle Abraham, research director, IDC. ”Google is a potential partner for organizations in the fight against existing and emerging threats.”</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/image1_lLkyWjS.max-1000x1000.png"
+
+ alt="image1">
+
+ </a>
+
+ <figcaption class="article-image__caption "><p data-block-key="06wt8">Google Security Operations is a unified, AI and intel-driven platform for threat detection, investigation, and response.</p></figcaption>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><h3><strong style="vertical-align: baseline;">Uncover the latest threats with curated detections</strong></h3>
+<p><span style="vertical-align: baseline;">To help reduce manual processes and provide better security outcomes for our customers, </span><a href="https://cloud.google.com/security/products/security-operations"><span style="text-decoration: underline; vertical-align: baseline;">Google Security Operations </span></a><span style="vertical-align: baseline;">includes a rich set of curated detections. Developed and maintained regularly by Google and Mandiant experts, curated detections can enable customers to detect threats relevant to their environment. Notable new curated detections include:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Cloud detections</strong><span style="vertical-align: baseline;"> can addresses serverless threats, cryptomining incidents across Google Cloud, all Google Cloud and Security Command Center Enterprise findings, anomalous user behavior rules, machine learning-generated lists of prioritized endpoint alerts (based on factors such as user and entity context), and baseline coverage for AWS including identity, compute, data services, and secret management. We have also added detections based on learnings from the Mandiant </span><a href="https://cloud.google.com/blog/products/identity-security/a-year-in-the-cybersecurity-trenches-with-mandiant-managed-defense"><span style="text-decoration: underline; vertical-align: baseline;">Managed Defense team</span></a><span style="vertical-align: baseline;">. Detections are now available in Google Security Operations Enterprise and Enterprise Plus packages. </span></p>
+</li>
+</ul>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Frontline threat detections</strong><span style="vertical-align: baseline;"> can provide coverage for recently-detected methodologies, and is based on threat actor tactics, techniques and procedures (TTPs), including from nation-states and newly-detected malware families. New threats discovered by Mandiant’s elite team, including during incident response engagements, are then made available as detections. It is now available in the Google Security Operations Enterprise Plus package. </span></p>
+</li>
+</ul>
+<h3><strong style="vertical-align: baseline;">Drive productivity for all with AI-powered SecOps </strong></h3>
+<p><span style="vertical-align: baseline;">The addition of Gemini in Security Operations can elevate the skills of your security team. It can help reduce the time security analysts spend writing, running, and refining searches and triaging complex cases by approximately sevenfold. Security teams can search for additional context, better understand threat actor campaigns and tactics, initiate response sequences and receive guided recommendations on next steps — all using natural language. Today we are sharing two exciting updates to Gemini in Security Operations.</span></p>
+<p><span style="vertical-align: baseline;">Now generally available, the </span><strong style="vertical-align: baseline;">Investigation Assistant</strong><span style="vertical-align: baseline;"> feature can help security professionals make faster decisions and respond to threats with more precision and speed by answering questions, summarizing events, hunting for threats, creating rules, and receiving recommended actions based on the context of investigations.</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/original_images/2_-_Investigation_Assistant.gif"
+
+ alt="2 - Investigation Assistant">
+
+ </a>
+
+ <figcaption class="article-image__caption "><p data-block-key="06wt8">Investigation Assistant can help answer questions, summarize events, hunt for threats, create rules, and recommend actions.</p></figcaption>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><strong style="vertical-align: baseline;">Playbook Assistant</strong><span style="vertical-align: baseline;">, now in preview, can help teams easily build response playbooks, customize configurations, and incorporate best practices — helping simplify time-consuming tasks that require deep expertise.</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/original_images/3_-_Playbook_Assistant.gif"
+
+ alt="3 - Playbook Assistant">
+
+ </a>
+
+ <figcaption class="article-image__caption "><p data-block-key="06wt8">Playbook Assistant can help build response playbooks, customize configurations, and incorporate best practices.</p></figcaption>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><h3><strong style="vertical-align: baseline;">Reduce manual work with autonomous parsers </strong></h3>
+<p><span style="vertical-align: baseline;">Getting data into the system and maintaining the pipeline is a critical yet time consuming task in security operations. As log sources change and new fields need to be extracted, security engineers and architects are often required to spend considerable time writing new parsing logic and ensuring backward compatibility. </span></p>
+<p><span style="vertical-align: baseline;">Today we are excited to announce that Google Security Operations can now </span><strong style="vertical-align: baseline;">automatically parse log files</strong><span style="vertical-align: baseline;"> by extracting all key-value pairs to make them available for search, rules, and analytics. Available in preview, automatic parsing can help reduce the maintenance overhead of parsers in general, and also reduce the time consuming task of creating custom parsers. It supports JSON-based logs, and we will be adding support for other log formats. Automatically parsing log files can help security teams have the right data and context, making for faster and more effective investigations and detection authoring.</span></p></div>
+<div class="block-video">
+
+
+
+<div class="article-module article-video ">
+ <figure>
+ <a class="h-c-video h-c-video--marquee"
+ href="https://youtube.com/watch?v=23rAFK1l4l8"
+ data-glue-modal-trigger="uni-modal-23rAFK1l4l8-"
+ data-glue-modal-disabled-on-mobile="true">
+
+
+
+
+ <div class="article-video__aspect-image"
+ style="background-image: url(https://storage.googleapis.com/gweb-cloudblog-publish/images/4-_Google_Cloud_YouTube__WhyCustomersLove.max-1000x1000.jpg);">
+ <span class="h-u-visually-hidden">Hear Why Customers Love Google Security Operations</span>
+ </div>
+
+ <svg role="img" class="h-c-video__play h-c-icon h-c-icon--color-white">
+ <use xlink:href="#mi-youtube-icon"></use>
+ </svg>
+ </a>
+
+
+ </figure>
+</div>
+
+<div class="h-c-modal--video"
+ data-glue-modal="uni-modal-23rAFK1l4l8-"
+ data-glue-modal-close-label="Close Dialog">
+ <a class="glue-yt-video"
+ data-glue-yt-video-autoplay="true"
+ data-glue-yt-video-height="99%"
+ data-glue-yt-video-vid="23rAFK1l4l8"
+ data-glue-yt-video-width="100%"
+ href="https://youtube.com/watch?v=23rAFK1l4l8"
+ ng-cloak>
+ </a>
+</div>
+
+</div>
+<div class="block-paragraph_advanced"><h3><strong style="vertical-align: baseline;">Raise the bar for defense</strong></h3>
+<p><span style="vertical-align: baseline;">For customers in need of expert support for managing Google Security Operations, we’ve got you covered. Google Security Operations can also work in concert with Mandiant Managed Defense and Mandiant Hunt, which can help you to reduce risks to your organization. Mandiant's team of seasoned defenders, analysts, and threat hunters work seamlessly with your security team and the AI-infused capabilities of Google Security Operations to quickly and effectively hunt or monitor, detect, triage, investigate, and respond to incidents. </span></p>
+<p><span style="vertical-align: baseline;">And for our public sector customers that may have more specialized requirements, we offer </span><a href="https://youtu.be/Uw5glgDmDhc?t=1709" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Google SecOps CyberShield</span></a><span style="vertical-align: baseline;"> to help governments worldwide build an enhanced cyber threat capability. </span></p>
+<p><span style="vertical-align: baseline;">To learn more about Google Security Operations, and the rest of Google Cloud Security’s comprehensive portfolio including an </span><a href="https://cloud.google.com/blog/products/identity-security/chrome-enterprise-expands-ecosystem-to-strengthen-endpoint-security-at-rsa"><span style="text-decoration: underline; vertical-align: baseline;">expanded Chrome Enterprise ecosystem</span></a><span style="vertical-align: baseline;">, come meet us in person at our </span><a href="https://www.rsaconference.com/usa/expo-and-sponsors/sponsor-details/google-cloud%20security-1690826518852001xqzp" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">RSA Conference booth</span></a><span style="vertical-align: baseline;"> (N5644). You can also catch us at our </span><a href="https://cloud.google.com/blog/products/identity-security/your-insiders-guide-to-google-cloud-security-at-rsa-conference-2024"><span style="text-decoration: underline; vertical-align: baseline;">keynotes, presentations, and meetups</span></a><span style="vertical-align: baseline;"> including our session, “</span><a href="https://www.rsaconference.com/usa/agenda/session/Bye-Bye%20DIY%20Frictionless%20Security%20Operations%20with%20Google" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Bye-Bye DIY: Frictionless Security Operations with Google</span></a><span style="vertical-align: baseline;">,” on Tuesday, May 7, at 1:15 p.m. PDT. </span></p>
+<p><span style="vertical-align: baseline;">Not attending RSAC? Join us for our upcoming webinar, “</span><a href="https://www.brighttalk.com/webcast/18282/610656?utm_source=GoogleCloudSecurity&utm_medium=email&utm_campaign=610656" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Stay ahead of the latest threats with intelligence-driven security operations</span></a><span style="vertical-align: baseline;">,” on Wednesday, May 22, at 11:00 a.m. PDT. </span></p></div>Mon, 06 May 2024 13:00:00 +0000https://cloud.google.com/blog/products/identity-security/introducing-google-security-operations-intel-driven-ai-powered-secops-at-rsa/Security & IdentityarticleIntroducing Google Security Operations: Intel-driven, AI-powered SecOpshttps://storage.googleapis.com/gweb-cloudblog-publish/images/0-_blog_header_-_19132_Security_BlogHeader_2.max-600x600.pngGooglehttps://cloud.google.com/blog/products/identity-security/introducing-google-security-operations-intel-driven-ai-powered-secops-at-rsa/Chris CordeDirector, Product ManagementIntroducing Google Threat Intelligence: Actionable threat intelligence at Google scalehttps://cloud.google.com/blog/products/identity-security/introducing-google-threat-intelligence-actionable-threat-intelligence-at-google-scale-at-rsa/<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">For decades, threat intelligence solutions have had two main challenges: They lack a comprehensive view of the threat landscape, and to get value from intelligence, organizations have to spend excess time, energy, and money trying to collect and operationalize the data. </span></p>
+<p><span style="vertical-align: baseline;">Today at the RSA Conference in San Francisco, we are announcing </span><a href="https://cloud.google.com/security/products/threat-intelligence/?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Google Threat Intelligence</span></a><span style="vertical-align: baseline;">, a new offering that combines the unmatched depth of our Mandiant frontline expertise, the global reach of the VirusTotal community, and the breadth of visibility only Google can deliver, based on billions of signals across devices and emails. Google Threat Intelligence includes Gemini in Threat Intelligence, our AI-powered agent that provides conversational search across our vast repository of threat intelligence, enabling customers to gain insights and protect themselves from threats faster than ever before.</span></p>
+<p><span style="vertical-align: baseline;">“While there is no shortage of threat intelligence available, the challenge for most is to contextualize and operationalize intelligence relevant to their specific organization,” said Dave Gruber, principal analyst, Enterprise Strategy Group. “Unarguably, Google provides two of the most important pillars of threat intelligence in the industry today with VirusTotal and Mandiant. Integrating both into a single offering, enhanced with AI and Google threat insights, offers security teams a new means to operationalize actionable threat intelligence to better protect their organizations.”</span></p>
+<h3><span style="vertical-align: baseline;">Unmatched visibility into threats</span></h3>
+<p><span style="vertical-align: baseline;">Google Threat Intelligence provides unparalleled visibility into the global threat landscape. We offer deep insights from Mandiant’s leading incident response and threat research team, and combine them with our massive user and device footprint and VirusTotal’s broad crowdsourced malware database. </span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Google threat insights: </strong><span style="vertical-align: baseline;">Google protects 4 billion devices and 1.5 billion email accounts, and blocks 100 million phishing attempts per day. This provides us with a vast sensor array and a unique perspective on internet and email-borne threats that allow us to connect the dots back to attack campaigns.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Frontline intelligence:</strong><span style="vertical-align: baseline;"> Mandiant's eIite incident responders and security consultants dissect attacker tactics and techniques, using their experience to help customers defend against sophisticated and relentless threat actors across the globe in over 1,100 investigations annually.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Human-curated threat intelligence:</strong><span style="vertical-align: baseline;"> Mandiant’s global threat experts meticulously monitor threat actor groups for activity and changes in their behavior to contextualize ongoing investigations and provide the insights you need to respond. </span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Crowdsourced threat intelligence:</strong><span style="vertical-align: baseline;"> VirusTotal's global community of over 1 million users continuously contributes potential threat indicators, including files and URLs, to offer real-time insight into emerging attacks.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Open-source threat intelligence</strong><span style="vertical-align: baseline;">: We use open-source threat intelligence to enrich our knowledge base with current discoveries from the security community.</span></p>
+</li>
+</ul></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--medium
+
+
+ h-c-grid__col
+
+ h-c-grid__col--4 h-c-grid__col--offset-4
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/1_-_vision_wheel.max-1000x1000.png"
+
+ alt="1 - vision wheel">
+
+ </a>
+
+ <figcaption class="article-image__caption "><p data-block-key="g00bm">Google Threat Intelligence boasts a diverse set of sources that provide a panoramic view of the global threat landscape and the granular details needed to make informed decisions.</p></figcaption>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">This comprehensive view allows Google Threat Intelligence to help protect your organization in a variety of ways, including external threat monitoring, attack surface management, digital risk protection, Indicators of Compromise (IOC) analysis, and expertise.</span></p>
+<h3><span style="vertical-align: baseline;">AI-driven operationalization</span></h3>
+<p><span style="vertical-align: baseline;">Traditional approaches to operationalizing threat intelligence are labor-intensive and can slow down your ability to respond to evolving threats, potentially taking days or weeks to respond.</span></p></div>
+<div class="block-video">
+
+
+
+<div class="article-module article-video ">
+ <figure>
+ <a class="h-c-video h-c-video--marquee"
+ href="https://youtube.com/watch?v=QGUri8v4THc"
+ data-glue-modal-trigger="uni-modal-QGUri8v4THc-"
+ data-glue-modal-disabled-on-mobile="true">
+
+
+
+
+ <div class="article-video__aspect-image"
+ style="background-image: url(https://storage.googleapis.com/gweb-cloudblog-publish/images/2_-_Code_Insights_thumbnail.max-1000x1000.png);">
+ <span class="h-u-visually-hidden">Google Threat Intelligence - Code Insights</span>
+ </div>
+
+ <svg role="img" class="h-c-video__play h-c-icon h-c-icon--color-white">
+ <use xlink:href="#mi-youtube-icon"></use>
+ </svg>
+ </a>
+
+
+ <figcaption class="article-video__caption h-c-page">
+
+ <h4 class="h-c-headline h-c-headline--four h-u-font-weight-medium h-u-mt-std">Google Threat Intelligence uses Gemini to analyze potentially malicious code and provides a summary of its findings.</h4>
+
+
+ </figcaption>
+
+ </figure>
+</div>
+
+<div class="h-c-modal--video"
+ data-glue-modal="uni-modal-QGUri8v4THc-"
+ data-glue-modal-close-label="Close Dialog">
+ <a class="glue-yt-video"
+ data-glue-yt-video-autoplay="true"
+ data-glue-yt-video-height="99%"
+ data-glue-yt-video-vid="QGUri8v4THc"
+ data-glue-yt-video-width="100%"
+ href="https://youtube.com/watch?v=QGUri8v4THc"
+ ng-cloak>
+ </a>
+</div>
+
+</div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">By combining our comprehensive view of the threat landscape with Gemini, we have supercharged the threat research processes, augmented defense capabilities, and reduced the time it takes to identify and protect against novel threats. Customers now have the ability to condense large data sets in seconds, quickly analyze suspicious files, and simplify challenging manual threat intelligence tasks.</span></p>
+<h3><strong style="vertical-align: baseline;">How Gemini helps simplify and assist with threat intelligence</strong></h3>
+<p><span style="vertical-align: baseline;">Gemini 1.5 Pro is a valuable part of Google Threat Intelligence, and we’ve integrated it so that it can more efficiently and effectively assist security professionals in combating malware.</span></p>
+<p><span style="vertical-align: baseline;">Gemini 1.5 Pro </span><span style="vertical-align: baseline;">offers the world’s longest context window, with support for up to </span><a href="https://blog.google/technology/ai/google-gemini-next-generation-model-february-2024/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">1 million tokens</span></a><span style="vertical-align: baseline;">. It </span><span style="vertical-align: baseline;">can dramatically simplify the technical and labor-intensive process of reverse engineering malware — one of the most advanced malware-analysis techniques available to cybersecurity professionals. In fact, it was able to process the entire decompiled code of the malware file for </span><a href="https://cloud.google.com/blog/topics/threat-intelligence/gemini-for-malware-analysis"><span style="text-decoration: underline; vertical-align: baseline;">WannaCry in a single pass</span></a><span style="vertical-align: baseline;">, taking 34 seconds to deliver its analysis and identify the killswitch.</span></p>
+<p><span style="vertical-align: baseline;">We also offer a Gemini-driven entity extraction tool to automate data fusion and enrichment. It can automatically crawl the web for relevant open source intelligence (OSINT), and classify online industry threat reporting. It then converts this information to knowledge collections, with corresponding hunting and response packs pulled from motivations, targets, tactics, techniques, and procedures (TTPs), actors, toolkits, and Indicators of Compromise (IoCs).</span></p>
+<p><span style="vertical-align: baseline;">Google Threat Intelligence can </span><span style="vertical-align: baseline;">distill more than a decade of threat reports to produce comprehensive, custom summaries in seconds.</span></p>
+<h3><strong style="vertical-align: baseline;">Make Google part of your security team</strong></h3>
+<p><span style="vertical-align: baseline;">Google Threat Intelligence is just one way we can help you in your threat intelligence journey. Whether you need cyber threat intelligence training for your staff, assistance with prioritizing complex threats, or even a dedicated threat analyst embedded in your team, our experts can act as an extension of your own team.</span></p>
+<p><span style="vertical-align: baseline;">Google Threat Intelligence is part of Google Cloud Security’s comprehensive security portfolio, which includes </span><a href="https://cloud.google.com/blog/products/identity-security/introducing-google-security-operations-intel-driven-ai-powered-secops-at-rsa"><span style="text-decoration: underline; vertical-align: baseline;">Google Security Operations</span></a><span style="vertical-align: baseline;">, </span><a href="https://cloud.google.com/security/consulting/mandiant-services/?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Mandiant Consulting</span></a><span style="vertical-align: baseline;">, </span><a href="https://cloud.google.com/blog/products/identity-security/cloud-ciso-perspectives-tour-the-new-security-command-center-enterprise/"><span style="text-decoration: underline; vertical-align: baseline;">Security Command Center Enterprise</span></a><span style="vertical-align: baseline;">, and </span><a href="https://cloud.google.com/blog/products/identity-security/chrome-enterprise-expands-ecosystem-to-strengthen-endpoint-security-at-rsa"><span style="text-decoration: underline; vertical-align: baseline;">Chrome Enterprise</span></a><span style="vertical-align: baseline;">. With our offerings, organizations can address security challenges with the same capabilities Google uses to keep more people and organizations safe online than anyone else in the world.</span></p>
+<p><span style="vertical-align: baseline;">To learn more about </span><a href="https://cloud.google.com/security/products/threat-intelligence?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Google Threat Intelligence</span></a><span style="vertical-align: baseline;"> and the rest of Google Cloud Security’s comprehensive portfolio, come meet us in person at our </span><a href="https://www.rsaconference.com/usa/expo-and-sponsors/sponsor-details/google-cloud%20security-1690826518852001xqzp" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">RSA Conference booth</span></a><span style="vertical-align: baseline;"> (N5644), and catch us at our </span><a href="https://cloud.google.com/blog/products/identity-security/your-insiders-guide-to-google-cloud-security-at-rsa-conference-2024"><span style="text-decoration: underline; vertical-align: baseline;">keynotes, presentations, and meetups</span></a><span style="vertical-align: baseline;">. </span><span style="vertical-align: baseline;">You can also register for our upcoming </span><a href="https://series.brighttalk.com/series/6490?utm_source=MandiantNA&utm_medium=BrightTALK&utm_campaign=6490" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Google Threat Intelligence use-cases webinar series</span></a><span style="vertical-align: baseline;">, and read our expert analysis and in-depth research at the Google Cloud </span><a href="https://cloud.google.com/blog/topics/threat-intelligence"><span style="text-decoration: underline; vertical-align: baseline;">Threat Intelligence blog</span></a><span style="vertical-align: baseline;">.</span></p></div>Mon, 06 May 2024 13:00:00 +0000https://cloud.google.com/blog/products/identity-security/introducing-google-threat-intelligence-actionable-threat-intelligence-at-google-scale-at-rsa/Security & IdentityarticleIntroducing Google Threat Intelligence: Actionable threat intelligence at Google scalehttps://storage.googleapis.com/gweb-cloudblog-publish/images/vision_circle.max-600x600.jpgGooglehttps://cloud.google.com/blog/products/identity-security/introducing-google-threat-intelligence-actionable-threat-intelligence-at-google-scale-at-rsa/Sunil PottiVP/GM, Google Cloud SecuritySandra JoyceVP, Google Threat IntelligenceChrome Enterprise expands ecosystem to strengthen endpoint security and Zero Trust accesshttps://cloud.google.com/blog/products/identity-security/chrome-enterprise-expands-ecosystem-to-strengthen-endpoint-security-at-rsa/<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">The modern workplace relies on web-based applications and cloud services, making browsers and their sensitive data a primary target for attackers. While the risks are significant, </span><a href="https://chromeenterprise.google/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Chrome Enterprise</span></a><span style="vertical-align: baseline;"> can help organizations simplify and strengthen their endpoint security with secure enterprise browsing. </span></p>
+<p><span style="vertical-align: baseline;">Following our recent </span><a href="https://cloud.google.com/blog/products/identity-security/introducing-chrome-enterprise-premium"><span style="text-decoration: underline; vertical-align: baseline;">Chrome Enterprise Premium</span></a><span style="vertical-align: baseline;"> launch, today at the RSA Conference in San Francisco, we’re announcing a growing ecosystem of security providers who are working with us to extend Chrome Enterprise’s browser-based protections and help enterprises protect their users working on the web and across corporate applications. </span></p>
+<h3><strong style="vertical-align: baseline;">Expanding Zero Trust protections with Zscaler</strong></h3>
+<p><span><span style="vertical-align: baseline;">Chrome Enterprise Premium offers advanced security across SaaS and private web applications for enterprises. Many organizations rely on </span><a href="https://www.zscaler.com/press/zscaler-joins-forces-google-offer-unparalleled-zero-trust-data-and-threat-protection" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Zscaler Private Access (ZPA)</span></a><span style="vertical-align: baseline;"> as an improved option over VPNs and firewalls to provide secure, Zero Trust access to private applications on-premises and in the cloud. Now security operations teams can add a layer of additional safeguards through Chrome Enterprise Premium, including: </span></span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Data protections</strong><span style="vertical-align: baseline;">: <span style="vertical-align: baseline;">Critical DLP functions including data exfiltration controls, copy, paste, and print restrictions, and watermarking capabilities. This complements Zscaler's data protection across endpoints, email, SaaS and cloud.</span></span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Threat prevention</strong><span style="vertical-align: baseline;">: Advanced malware scanning, real-time phishing security, and credential protections, augmenting Zscaler's inline inspection of encrypted traffic and built in threat protections.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Security insights</strong><span style="vertical-align: baseline;">: Additional telemetry and reporting across insider and external risks.</span></p>
+</li>
+</ul>
+<p><span style="vertical-align: baseline;">Google has collaborated with Zscaler to provide enterprises with a </span><a href="https://www.zscaler.com/resources/solution-briefs/zs-private-access-google-chrome-enterprise.pdf" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">solution guide</span></a><span style="vertical-align: baseline;"> that enables organizations to configure their network security products alongside Chrome Enterprise Premium for deeper security and protections.</span></p>
+<h3><strong style="vertical-align: baseline;">Browser-based device trust with Cisco Duo</strong></h3>
+<p><span style="vertical-align: baseline;">As attacks targeting end-users become more sophisticated, a multi-layered defense that includes a strong device access policy is crucial. Signals including user identity, device security, and location can enable dynamic, risk-based access decisions that further protect corporate data. </span></p>
+<p><span style="vertical-align: baseline;">Enterprises can now use </span><a href="https://duo.com/partnerships/technology-partners/select-partners/google" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Duo Trusted Endpoints policy</span></a><span style="vertical-align: baseline;"> to enforce</span><span style="vertical-align: baseline;"> </span><a href="https://duo.com/product/device-trust" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">device trust</span></a><span style="vertical-align: baseline;"> using built-in Chrome Enterprise signals to deny access from unknown devices — without having to deploy additional agents and extensions. This integration allows organizations to:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Verify endpoint trust at login, and block unknown devices</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Manage device access from a centralized Duo dashboard</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Adjust granular policies for an organization of any size in a few clicks</span></p>
+</li>
+</ul></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/2_-_CE_and_Duo_Screenshot.max-1000x1000.png"
+
+ alt="2 - CE and Duo Screenshot">
+
+ </a>
+
+ <figcaption class="article-image__caption "><p data-block-key="9ox4v">Duo's Trusted Endpoints feature lets organizations grant secure access to applications with policies that verify systems using signals from Chrome.</p></figcaption>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><h3><strong style="vertical-align: baseline;">Data loss prevention with Trellix</strong></h3>
+<p><span style="vertical-align: baseline;">Data loss remains a top concern for enterprises, and the browser is a critical point for stopping data leaks. </span><a href="https://www.trellix.com/assets/data-sheets/trellix-dlp-for-chrome-enterprise-data-sheet.pdf" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Trellix DLP</span></a><span style="vertical-align: baseline;"> for Chrome Enterprise is now available as an integration to customers managing Chrome from the cloud. With the Trellix DLP integration, organizations can prevent data leaks in Chrome by:</span></p>
+<ul>
+<li role="presentation"><span style="vertical-align: baseline;">Monitoring and blocking file uploads with sensitive content</span></li>
+<li role="presentation"><span style="vertical-align: baseline;">Tracking and preventing sensitive content from being copied and pasted to websites</span></li>
+<li role="presentation"><span style="vertical-align: baseline;">Controlling print activity in Chrome browser and on local workstations</span></li>
+</ul>
+<p> </p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/3_-_CE_and_Trellix_Screenshot.max-1000x1000.png"
+
+ alt="3 - CE and Trellix Screenshot">
+
+ </a>
+
+ <figcaption class="article-image__caption "><p data-block-key="9ox4v">When sensitive information is detected in Chrome, the user is immediately notified with a pop-up.</p></figcaption>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Current Trellix DLP and Cisco Duo customers can implement these integrations by enrolling browsers into </span><a href="https://chromeenterprise.google/products/cloud-management/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Chrome Enterprise Core</span></a><span style="vertical-align: baseline;"> and setting up a one-time configuration, at no additional cost. Learn more about the Trellix DLP integration here and Cisco Duo integration </span><a href="https://chromeenterprise.google/solutions/integrations/?modal-id=ciscoduo" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">here</span></a><span style="vertical-align: baseline;">. </span></p>
+<h3><strong style="vertical-align: baseline;">Take the next step</strong></h3>
+<p><span style="vertical-align: baseline;">To learn more about Chrome Enterprise, and the rest of Google Cloud Security’s comprehensive portfolio including our RSAC announcements on </span><a href="https://cloud.google.com/blog/products/identity-security/advancing-the-art-of-ai-driven-security-with-google-cloud-at-rsa"><span style="text-decoration: underline; vertical-align: baseline;">Google Cloud Security and AI</span></a><span style="vertical-align: baseline;">, </span><a href="https://cloud.google.com/blog/products/identity-security/introducing-google-threat-intelligence-actionable-threat-intelligence-at-google-scale-at-rsa"><span style="text-decoration: underline; vertical-align: baseline;">Google Threat Intelligence</span></a><span style="vertical-align: baseline;">, and </span><a href="https://cloud.google.com/blog/products/identity-security/introducing-google-security-operations-intel-driven-ai-powered-secops-at-rsa"><span style="text-decoration: underline; vertical-align: baseline;">Google Security Operations</span></a><span style="vertical-align: baseline;">, come meet us in person at our </span><a href="https://www.rsaconference.com/usa/expo-and-sponsors/sponsor-details/google-cloud%20security-1690826518852001xqzp" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">RSA Conference booth</span></a><span style="vertical-align: baseline;"> (N5644), and catch us at our </span><a href="https://cloud.google.com/blog/products/identity-security/your-insiders-guide-to-google-cloud-security-at-rsa-conference-2024"><span style="text-decoration: underline; vertical-align: baseline;">keynotes, presentations, and meetups</span></a><span style="vertical-align: baseline;">. You can also learn more about </span><a href="https://chromeenterprise.google/products/chrome-enterprise-premium/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Chrome Enterprise here</span></a><span style="vertical-align: baseline;">.</span></p></div>Mon, 06 May 2024 13:00:00 +0000https://cloud.google.com/blog/products/identity-security/chrome-enterprise-expands-ecosystem-to-strengthen-endpoint-security-at-rsa/Chrome EnterpriseSecurity & IdentityarticleChrome Enterprise expands ecosystem to strengthen endpoint security and Zero Trust accesshttps://storage.googleapis.com/gweb-cloudblog-publish/images/1-_Blog_header_banner.max-600x600.pngGooglehttps://cloud.google.com/blog/products/identity-security/chrome-enterprise-expands-ecosystem-to-strengthen-endpoint-security-at-rsa/Kiran NairSenior Product Manager, Chrome Enterprise, GoogleUncomplicating the complex: How Spanner simplifies microservices-based architectureshttps://cloud.google.com/blog/products/databases/why-spanner-is-a-good-fit-for-microservices-based-applications/<div class="block-paragraph_advanced"><p style="text-align: justify;"><span style="vertical-align: baseline;">In the realm of modern application design, developers have a range of choices available to them for crafting architectures that are not only simple, but also scalable, performant and resilient. Container platforms like Kubernetes (k8s) offer users the ability to seamlessly adjust node and pod specifications, so that services can scale. This scalability does not come at the expense of elasticity, and also ensures consistent performance for service consumers. So it’s no surprise that Kubernetes has become the de facto standard for building distributed and resilient systems in medium-to-large organizations.</span></p>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">Unfortunately, the level of maturity and standardization in the Kubernetes space available to system designers in the application layer doesn’t usually extend to the database layer that powers these services. And it goes without saying that the database layer also needs to be elastic, scalable, highly available, and resilient. </span></p>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">Further, the challenges are amplified when these services:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><span style="vertical-align: baseline;">Are required to manage (transactional) states or </span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><span style="vertical-align: baseline;">Orchestrate distributed processes across multiple (micro-) services. </span></p>
+</li>
+</ul>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">Traditional relational database management software (RDBMS) brings with it side effects that are not aligned with a microservices way of thinking, and entails fairly significant trade-offs. In the sections below, we dive deeper into the scalability, availability and operational challenges faced by application designers specifically within the database tier. We then conclude with a description of how Spanner can help you build microservices-based systems without the often unspoken “impedance mismatch” between the application layer and the database layer.</span></p>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">We look at this problem from a scalability and availability perspective, specifically in the context of databases that cater to OLTP workloads. We explore the intricacies involved in accommodating highly variable workloads, shedding light on the complexities associated with managing higher demands through the utilization of both replicas and sharding techniques.</span></p>
+<h2 style="text-align: justify;"><strong style="vertical-align: baseline;">Wanted: scalability and availability</strong></h2>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">When it comes to scaling a traditional relational database, you have two choices (leaving aside caching strategies):</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><strong style="vertical-align: baseline;">Scale up:</strong><span style="vertical-align: baseline;"> To scale a database vertically, you typically augment its resources by adding more CPU power, increasing memory, or adding faster disks. However, these scale-up procedures usually incur downtime, affecting the availability of dependent services. </span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><strong style="vertical-align: baseline;">Scale out:</strong><span style="vertical-align: baseline;"> Although vertically scaling up databases can be effective initially, it eventually encounters limitations. The alternative is to scale out database traffic, by introducing additional read replicas, employing sharding techniques, or even a combination of both. These methods come with their own trade-offs and introduce complexities, which lead to operational overhead.</span></p>
+</li>
+</ul>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">In terms of </span><strong style="vertical-align: baseline;">availability</strong><span style="vertical-align: baseline;">, databases require maintenance, resulting in the need to coordinate regular periods of downtime. Relational databases can also be prone to hardware defects, network partitions, or subject to data center outages that bring a host of DR scenario challenges that you need to address and plan for. </span></p>
+<p><strong style="vertical-align: baseline;">Examples of planned downtime:</strong></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">OS or database engine upgrades or patches </span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Schema changes - Most database engines require downtime for the duration of a schema change</span></p>
+</li>
+</ul>
+<p><strong style="vertical-align: baseline;">Examples of unplanned downtime</strong></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Zonal or regional outages</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Network partitions</span></p>
+</li>
+</ul>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">Most “mature” practices for handling traditional RDBMSs run counter to modern application design principles and can significantly impact the availability and performance of services. Depending on the nature of the business, this can have consequences for revenue streams, compliance with regulations, or adversely impact customer satisfaction.</span></p>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">Let’s go over some of the key challenges associated with RDBMSs.</span></p>
+<h3 style="text-align: justify;"><strong style="vertical-align: baseline;">Challenges associated with read-replicas</strong></h3></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/1-READ-REPLICAS.max-1000x1000.png"
+
+ alt="1-READ-REPLICAS">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Database read replicas are a suitable tool for scaling out read operations and mitigating planned downtime, so that reads are at least available to the application layer. </span></p>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">In order to reduce load on the primary database instance, replicas can be created to distribute read load across multiple machines and thus handle more read requests concurrently. </span></p>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">Replication between the primary and secondary replicas is usually done asynchronously. This means there can be a lag between when data is written to the primary database and when it is replicated to the read replicas. This can result in read operations getting slightly outdated (stale) data if they are directed to the replicas. This also dictates that guaranteed consistent queries need to be directed to primary instances. Synchronous replication is rarely an option, in particular, not in geo-distributed topologies, as it is complex, and comes with a range of issues such as:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><span style="vertical-align: baseline;">Limiting the scalability of the system, as every write operation must wait for confirmation from the replica, causing performance bottlenecks and increasing latency</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><span style="vertical-align: baseline;">Introducing a single point of failure — if the replica becomes unavailable or experiences issues, it can impact the availability of the primary database as well</span></p>
+</li>
+</ul>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">And lastly, write throughput can become bottlenecked due to the limit on how much write traffic a single database can handle without performance degradation. Scaling writes still requires vertical scaling (more powerful hardware) or sharding (splitting data across multiple databases), which can lead to downtime, additional costs, and limits imposed by non-linearly escalating operational toil. Now let’s look at sharding challenges in a bit more detail.</span></p>
+<h3 style="text-align: justify;"><strong style="vertical-align: baseline;">Sharding challenges</strong></h3></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/2-SHARDING.max-1000x1000.png"
+
+ alt="2-SHARDING">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p style="text-align: justify;"><span style="vertical-align: baseline;">Sharding is a powerful tool for database scalability. When implemented correctly, it can enable applications to handle a much larger volume of read and write transactions. However, sharding does not come without its challenges and brings its own set of complexities that need careful navigation.</span></p>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">There are multiple ways to shard databases. For instance, </span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><span style="vertical-align: baseline;">they can be split by user id ranges, </span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><span style="vertical-align: baseline;">regions or </span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><span style="vertical-align: baseline;">channels (e.g. web, mobile) etc.. </span></p>
+</li>
+</ul>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">As shown in the above example, sharding by user id or region can lead to significant performance improvements, as smaller data ranges are hosted by individual databases and the traffic can be spread across these databases.</span></p>
+<p style="text-align: justify;"><strong style="vertical-align: baseline;">Key considerations:</strong></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><strong style="vertical-align: baseline;">Deciding on the “right” kind of sharding: </strong><span style="vertical-align: baseline;">One of the primary challenges of sharding is the initial setup. Deciding on a sharding key, whether it be user ID, region, or another attribute, requires a deep understanding of your data access patterns. A poorly chosen sharding key can result in uneven data distribution, known as "shard imbalance," which can significantly dull the performance benefits of sharding.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><strong style="vertical-align: baseline;">Data integrity</strong><span style="vertical-align: baseline;"> is another significant concern. When data is spread across multiple shards, maintaining foreign-key relationships becomes difficult. Transactions that span multiple shards become complex and can result in increased latency and decreased integrity.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><strong style="vertical-align: baseline;">Operational complexity: </strong><span style="vertical-align: baseline;">Sharding introduces operational complexity. Managing multiple databases requires a more sophisticated approach to maintenance, backups, and monitoring. Each shard may need to be backed up separately, and restoring a sharded database to a consistent state can be challenging.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><strong style="vertical-align: baseline;">Re-sharding: </strong><span style="vertical-align: baseline;">As an application grows, the chosen sharding scheme might need to change. This process involves redistributing the data across a new set of shards, which can be time-consuming and risky, often requiring significant downtime or degraded performance during the transition.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><strong style="vertical-align: baseline;">Increased development complexity:</strong><span style="vertical-align: baseline;"> Application logic can become more complex because developers must account for the distribution of data. This could mean additional logic for routing queries to the correct shard, handling partial failures, and ensuring that transactions that need to operate across shards maintain consistency.</span></p>
+</li>
+</ul>
+<h3 style="text-align: justify;"><strong style="vertical-align: baseline;">Exploding complexity and operations</strong></h3></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/3-COMPLEXITY.max-1000x1000.png"
+
+ alt="3-COMPLEXITY">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p style="text-align: justify;"><span style="vertical-align: baseline;">Over time, database complexity can grow along with increased traffic, adding further toil to operations. For large systems, a combination of sharding along with attached scale-out read replicas might be required to help ensure cost-effective scalability and performance.</span></p>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">This combined dual-strategy approach, while effective in handling increasing traffic, significantly ramps up the complexity of the system's architecture. The above illustration captures the need to add scalability and availability to a transactional relational database powering a service. It doesn’t even include full details on DR (e.g. backups), or geo-redundancy, nor does it cater to zero-to-low RPO/RTO requirements. </span></p>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">Furthermore, the dual-strategy approach described above can:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><span style="vertical-align: baseline;">negatively impact the ease of service maintenance </span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><span style="vertical-align: baseline;">increase operational demands, and </span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><span style="vertical-align: baseline;">elevate the risk associated with the resolution of incidents</span></p>
+</li>
+</ul>
+<h2><strong style="vertical-align: baseline;">Doesn’t NoSQL address this?</strong></h2>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">NoSQL databases began to emerge in the early 2000s as a response to traditional RDBMSs’ above-mentioned limitations. In the new era of big data and web-scale applications, NoSQL databases were designed to overcome the challenges of scalability, performance, flexibility and availability that were imposed by the growing volume of semi-structured data. </span></p>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">However, the key tradeoff they made was to drop sound relational models, SQL, and support for ACID-compliant transactions. However, many prominent system architects have questioned the wisdom of abandoning these well-worn relational concepts for OLTP workloads, as they are essential features that still power mission-critical applications. As such, there’s been a recent trend to (re)introduce relational database features into NoSQL databases, such as ACID transactions in MongoDB and Cassandra Query Language (CQL) in Cassandra.</span></p>
+<h3 style="text-align: justify;"><strong style="vertical-align: baseline;">Enter Spanner</strong></h3></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--medium
+
+
+ h-c-grid__col
+
+ h-c-grid__col--4 h-c-grid__col--offset-4
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/4-SIMPLIFY-WITH-SPANNER.max-1000x1000.png"
+
+ alt="4-SIMPLIFY-WITH-SPANNER">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p style="text-align: justify;"><a href="https://cloud.google.com/spanner"><span style="text-decoration: underline; vertical-align: baseline;">Spanner</span></a><span style="vertical-align: baseline;"> eliminates much of this complexity and helps facilitate a simple and easy-to-maintain architecture without most of the above-mentioned compromises. It combines relational concepts and features (SQL, ACID transactions) with seamless horizontal scalability, providing geo-redundancy with up to 99.999% availability that you want when designing a microservices-based application.</span></p>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">We want to emphasize that we’re not arguing that Spanner is </span><span style="text-decoration: underline; vertical-align: baseline;">only</span><span style="vertical-align: baseline;"> a good fit for microservices. All the things that make Spanner a great fit for microservices also make it great for monolithic applications. </span></p>
+<p style="text-align: justify;"><span style="vertical-align: baseline;">To summarize, a microservices architecture built on Spanner allows software architects to design systems where both the application and database provide:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><span style="vertical-align: baseline;">“Scale insurance” for future growth scenarios</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><span style="vertical-align: baseline;">An easy way to handle traffic spikes</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><span style="vertical-align: baseline;">Cost efficiency through Spanner’s elastic and instant compute provisioning</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Up to 99.999% availability with geo-redundancy</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">No downtime windows (for maintenance or other upgrades)</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Enterprise-grade security such as encryption at rest and in-transit</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><span style="vertical-align: baseline;">Features to cater for transactional workloads</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation" style="text-align: justify;"><span style="vertical-align: baseline;">Increases in developer productivity (e.g. SQL)</span></p>
+</li>
+</ul>
+<p><span style="vertical-align: baseline;">You can </span><a href="https://goo.gle/SpannerDatabaseUnlimited" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">learn more</span></a><span style="vertical-align: baseline;"> about what makes Spanner unique and how it’s being used today. Or </span><a href="https://cloud.google.com/spanner/docs/free-trial-quickstart"><span style="text-decoration: underline; vertical-align: baseline;">try it yourself for free</span></a><span style="vertical-align: baseline;"> for 90-days or for as little as $65 USD/month for a production-ready instance that grows with your business without downtime or disruptive re-architecture.</span></p></div>Fri, 03 May 2024 16:00:00 +0000https://cloud.google.com/blog/products/databases/why-spanner-is-a-good-fit-for-microservices-based-applications/SpannerDatabasesarticleUncomplicating the complex: How Spanner simplifies microservices-based architecturesGooglehttps://cloud.google.com/blog/products/databases/why-spanner-is-a-good-fit-for-microservices-based-applications/Szabolcs RozsnyaiSenior Staff Solutions Architect, SpannerKarthi ThyagarajanSenior Staff Solutions Architect, SpannerMaking API calls exactly once when using Workflowshttps://cloud.google.com/blog/products/application-development/using-single-execution-calls-with-workflows/<div class="block-paragraph_advanced"><h2><strong style="vertical-align: baseline;">Introduction</strong></h2>
+<p><span style="vertical-align: baseline;">One challenge with any distributed system, including </span><a href="https://cloud.google.com/workflows"><span style="text-decoration: underline; vertical-align: baseline;">Workflows</span></a><span style="vertical-align: baseline;">, is ensuring that requests sent from one service to another are processed exactly once, when needed; for example, when placing a customer order in a shipping queue, withdrawing funds from a bank account, or processing a payment.</span></p>
+<p><span style="vertical-align: baseline;">In this blog post, we’ll provide an example of a website invoking Workflows, and Workflows in turn invoking</span><span style="vertical-align: baseline;"> </span><span style="vertical-align: baseline;">a </span><a href="https://cloud.google.com/functions"><span style="text-decoration: underline; vertical-align: baseline;">Cloud Function</span></a><span style="vertical-align: baseline;">. We’ll show how to make sure both Workflows and the Cloud Function logic only runs once. We’ll also talk about how to invoke Workflows exactly once when using </span><a href="https://cloud.google.com/blog/topics/developers-practitioners/introducing-workflows-callbacks"><span style="text-decoration: underline; vertical-align: baseline;">HTTP callbacks</span></a><span style="vertical-align: baseline;">, </span><a href="https://cloud.google.com/pubsub"><span style="text-decoration: underline; vertical-align: baseline;">Pub/Sub</span></a><span style="vertical-align: baseline;"> messages, or </span><a href="https://cloud.google.com/tasks"><span style="text-decoration: underline; vertical-align: baseline;">Cloud Tasks</span></a><span style="vertical-align: baseline;">.</span></p>
+<h2><strong style="vertical-align: baseline;">Invoke Workflows exactly once</strong></h2>
+<p><span style="vertical-align: baseline;">Imagine you have an online store and you’re using Workflows to create new orders, save to Firestore, and process payments by calling a Cloud Function:</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/image1_hVpeh5J.max-1000x1000.png"
+
+ alt="image1">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">A new customer order comes in, the website makes an API call to Workflows but receives an error. Two possible scenarios are:</span></p>
+<p><span style="vertical-align: baseline;"> (1) The request is lost and the workflow is never invoked:</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--medium
+
+
+ h-c-grid__col
+
+ h-c-grid__col--4 h-c-grid__col--offset-4
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/image2_1VaigE8.max-1000x1000.png"
+
+ alt="image2">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">(2) The workflow is invoked and executes successfully, however the response is lost:</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--medium
+
+
+ h-c-grid__col
+
+ h-c-grid__col--4 h-c-grid__col--offset-4
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/image3_Lfq82pR.max-1000x1000.png"
+
+ alt="image3">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">How can you make sure the workflow executes once?</span></p>
+<p><span style="vertical-align: baseline;">To solve this, the website retries the same request. One easy solution is to check if a document already exists in Firestore:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'main:\r\n params: []\r\n steps:\r\n - init:\r\n assign:\r\n - project_id: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}\r\n - order_id: "12345" # In practice we would pass in the order ID as a workflow parameter, e.g. ${params[0]}\r\n - firestore_collection: "orders"\r\n - URL: https://us-central1-<your_project_id>.cloudfunctions.net/processpayment\r\n - create_document:\r\n try:\r\n call: googleapis.firestore.v1.projects.databases.documents.createDocument\r\n args:\r\n collectionId: ${firestore_collection}\r\n parent: ${"projects/" + project_id + "/databases/(default)/documents"}\r\n query:\r\n documentId: ${order_id}\r\n except:\r\n as: e\r\n steps:\r\n - endEarly:\r\n return: ${e} # Exception is raised, e.g. ${e.code == 409} if doc already exists\r\n - processPayment:\r\n ...'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc698f910>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">The </span><code style="vertical-align: baseline;">processPayment </code><span style="vertical-align: baseline;">step will execute only if a document is successfully created. This is effectively a 1-bit state machine, idempotent, and a valid solution. The downside of this solution is that it’s not extensible. We might want to complete additional work in this handler before changing states, or expand the number of states within the system. Next, let’s continue with a more advanced solution for the same problem.</span></p>
+<h2><strong style="vertical-align: baseline;">Invoke Cloud Functions from Workflows exactly once</strong></h2>
+<p><span style="vertical-align: baseline;">Let’s see what happens when the workflow uses a Cloud Function to process the payment. You might have the following step to call Cloud Functions:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', '- processPayment:\r\n call: http.post\r\n args:\r\n url: https://us-central1-<your_project_id>.cloudfunctions.net/processpayment\r\n auth:\r\n type: OIDC'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc698feb0>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">By default, Workflows offers </span><strong style="vertical-align: baseline;">at-most-once</strong><span style="vertical-align: baseline;"> delivery (no retries) with HTTP requests. That’s usually OK because 99.9+% of the time, the call is successful, and a response is received.</span></p>
+<p><span style="vertical-align: baseline;">In the rare case of failure, a </span><a href="https://cloud.google.com/workflows/docs/reference/syntax/error-types#error-tags"><code style="text-decoration: underline; vertical-align: baseline;">ConnectionError</code></a><span style="vertical-align: baseline;"> might be raised. As in the website-to-workflow situation discussed previously, the workflow can’t tell which scenario occurred. Similarly, you can add retries. </span></p>
+<p><span style="vertical-align: baseline;">Let’s add a </span><a href="https://cloud.google.com/workflows/docs/reference/syntax/retrying#default-retry-policy"><span style="text-decoration: underline; vertical-align: baseline;">default retry policy</span></a><span style="vertical-align: baseline;"> to handle this:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', "- processPayment:\r\n try:\r\n call: http.post\r\n args:\r\n url: https://us-central1-<your_project_id>.cloudfunctions.net/processpayment\r\n auth:\r\n type: OIDC\r\n retry: ${http.default_retry} # Retries up to 5 times, includes 'ConnectionError'"), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc698f0a0>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Let's say the second delivery scenario occurs where the request is received by the Cloud Function but the response is lost. By adding retries, Workflows will likely invoke the Cloud Function multiple times. When this happens, how do you ensure that the code in the Cloud Function only runs once? </span></p>
+<p><span style="vertical-align: baseline;">You’ll need to add extra logic to the Cloud Function to check and update the payment state in Firestore:</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/image4_HtrYAfU.max-1000x1000.png"
+
+ alt="image4">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Let’s also assume you want to track the workflow </span><code style="vertical-align: baseline;">EXECUTION_ID</code><span style="vertical-align: baseline;"> in Firestore and use the following </span><code style="vertical-align: baseline;">order_state </code><span style="vertical-align: baseline;">enum to allow for additional flexibility in payment processing:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'payment_not_processed // Initial state when an order is created\r\npayment_declined // Payment was not successful\r\npayment_successful // Payment processed successfully\r\n...'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc85b8c40>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">You can expand on the previous workflow and call a Cloud Function to process the payment:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'main:\r\n params: []\r\n steps:\r\n - init:\r\n assign:\r\n - project_id: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}\r\n - order_id: "12345" # In practice we would pass in the order ID as a workflow parameter, e.g. ${params[0]}\r\n - firestore_collection: "orders"\r\n - URL: https://us-central1-<your_project_id>.cloudfunctions.net/processpayment\r\n - create_document:\r\n try:\r\n call: googleapis.firestore.v1.projects.databases.documents.createDocument\r\n args:\r\n collectionId: ${firestore_collection}\r\n parent: ${"projects/" + project_id + "/databases/(default)/documents"}\r\n query:\r\n documentId: ${order_id}\r\n body:\r\n fields:\r\n order_state: # We set an initial state\r\n stringValue: "payment_not_processed"\r\n workflow_id: # And also track this workflow execution ID\r\n stringValue: ${sys.get_env("GOOGLE_CLOUD_WORKFLOW_EXECUTION_ID")}\r\n except:\r\n as: e\r\n steps:\r\n - endEarly:\r\n return: ${e} # Exception is raised, e.g. ${e.code == 409} if doc already exists\r\n - processPayment:\r\n try:\r\n call: http.post\r\n args:\r\n url: ${URL} # Might get called multiple times!\r\n auth:\r\n type: OIDC\r\n body:\r\n order_id: ${order_id}\r\n result: r\r\n retry: ${http.default_retry}\r\n - returnStep:\r\n return: ${r}'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc85b8670>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Here’s the Cloud Function (Node.js v20) that processes the payment:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'const functions = require(\'@google-cloud/functions-framework\');\r\nconst firestore = require(\'@google-cloud/firestore\');\r\n\r\n\r\nfunctions.http(\'helloHttp\', (req, res) => {\r\n const fs = new firestore.Firestore();\r\n try{\r\n// Reads the current state from Firestore and updates it within the same transaction to make this handler idempotent. Using a transaction is important. Note: It could be run multiple times but will only be committed once.\r\n return fs.runTransaction(t => {\r\n const docRef = fs.doc("orders/" + req.body.order_id);\r\n return t.get(docRef).then(doc => {\r\n console.log(doc, \'=>\', doc);\r\n var state = doc.data().order_state\r\n // Only process the order if we haven\'t already\r\n if (state == "payment_not_processed") {\r\n // Do payment stuff, e.g. debit account from another Firestore document\r\n // ...\r\n //\r\n state = "payment_successful"\r\n t.update(docRef, {order_state: state})\r\n res.status(200).send(state);\r\n return\r\n }\r\n res.status(200).send("request ignored, state already: " + state);\r\n });\r\n }).then(result => {\r\n console.log(\'Transaction result: \', result);\r\n });\r\n } catch (e) {\r\n console.log(\'Transaction failure:\', e);\r\n } \r\n});'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc8110610>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><code style="vertical-align: baseline;">package.json</code></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', '{\r\n "dependencies": {\r\n "@google-cloud/functions-framework": "^3.3.0",\r\n "@google-cloud/firestore": "^7.6.0"\r\n }\r\n}'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc81107f0>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">The key takeaway is that all payment processing work occurs within a </span><strong style="vertical-align: baseline;">transaction</strong><span style="vertical-align: baseline;">, making all actions idempotent. The code within the transaction might run multiple times due to Workflows retries, but it’s only committed once. </span></p>
+<h2><strong style="vertical-align: baseline;">What about HTTP callbacks, Pub/Sub, Cloud Tasks?</strong></h2>
+<p><span style="vertical-align: baseline;">So far, we’ve talked about how to make website-to-workflow and Workflows to Cloud Functions requests, exactly once. There are other ways of invoking or resuming Workflows such as </span><a href="https://cloud.google.com/blog/topics/developers-practitioners/introducing-workflows-callbacks"><span style="text-decoration: underline; vertical-align: baseline;">HTTP callbacks</span></a><span style="vertical-align: baseline;">, Pub/Sub messages or Cloud Tasks. How do you make those requests exactly once? Let’s take a look.</span></p>
+<h3><strong style="vertical-align: baseline;">Callbacks</strong></h3>
+<p><span style="vertical-align: baseline;">The good news is that Workflows HTTP callbacks are fully idempotent by default. It’s safe to retry a callback if it fails. For example:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', '- createCallbackStep:\r\n call: events.create_callback_endpoint\r\n args:\r\n http_callback_method: "POST"\r\n result: callback_details\r\n- sendOutURL:\r\n call: http.post\r\n args:\r\n url: "https://your-endpoint.com/foo"\r\n body:\r\n callback_to_use: ${callback_details.url}\r\n...\r\n- callbackWaitStep:\r\n call: events.await_callback\r\n args:\r\n callback: ${callback_details}'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc8110220>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Let’s assume that the first callback returns an error to the external caller. Based on the error, the caller might not know if the workflow callback was received, and should retry the callback. On the second callback, the caller will receive one of the following HTTP status codes:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">429</strong><span style="vertical-align: baseline;"> indicates that the first callback was received successfully. The second callback is rejected by the workflow.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">200</strong><span style="vertical-align: baseline;"> indicates that the second callback was received successfully. The first callback was either never received, or was received and processed successfully. If the latter, the second callback is not processed because </span><code style="vertical-align: baseline;">await_callback </code><span style="vertical-align: baseline;">is called only once. The second callback is discarded at the end of the workflow.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">404</strong><span style="vertical-align: baseline;"> indicates that a callback is not available. Either the first callback was received and processed and the workflow has completed, or the workflow is not running (and has failed, for example). To confirm this, you’ll need to send an API request to query the workflow execution state.</span></p>
+</li>
+</ul>
+<p><span style="vertical-align: baseline;">For more details, see </span><a href="https://cloud.google.com/workflows/docs/creating-callback-endpoints#invoke-once"><span style="text-decoration: underline; vertical-align: baseline;">Invoke a workflow exactly once using callbacks</span></a><span style="vertical-align: baseline;">.</span></p>
+<h3><strong style="vertical-align: baseline;">Pub/Sub messages </strong></h3>
+<p><span style="vertical-align: baseline;">When using Pub/Sub to </span><a href="https://cloud.google.com/workflows/docs/trigger-workflow-eventarc"><span style="text-decoration: underline; vertical-align: baseline;">trigger</span></a><span style="vertical-align: baseline;"> a new workflow execution, Pub/Sub uses </span><strong style="vertical-align: baseline;">at-least-once</strong><span style="vertical-align: baseline;"> delivery with Workflows, and will retry on any delivery failure. Pub/Sub messages are automatically deduplicated. You don’t need to worry about duplicate deliveries in that time window (24 hours).</span></p>
+<h3><strong style="vertical-align: baseline;">Cloud Tasks</strong></h3>
+<p><span style="vertical-align: baseline;">Cloud Tasks is commonly used to </span><a href="https://cloud.google.com/workflows/docs/tutorials/buffer-workflows-executions"><span style="text-decoration: underline; vertical-align: baseline;">buffer workflow executions</span></a><span style="vertical-align: baseline;"> and provides </span><strong style="vertical-align: baseline;">at-least-once </strong><span style="vertical-align: baseline;">delivery but it </span><strong style="vertical-align: baseline;">doesn’t</strong><span style="vertical-align: baseline;"> have message deduplication. Workflow handlers </span><a href="https://cloud.google.com/tasks/docs/dual-overview"><span style="text-decoration: underline; vertical-align: baseline;">should be idempotent</span></a><span style="vertical-align: baseline;">.</span></p>
+<h2><strong style="vertical-align: baseline;">Conclusion</strong></h2>
+<p><span style="vertical-align: baseline;">Exactly-once request processing is a hard problem. In this blog post, we’ve outlined some scenarios where you might need exactly-once request processing when you’re using Workflows. We also provided some ideas on how you can implement it. The exact solution will depend on the actual use case and the services involved.</span></p></div>Fri, 03 May 2024 16:00:00 +0000https://cloud.google.com/blog/products/application-development/using-single-execution-calls-with-workflows/Developers & PractitionersApplication DevelopmentarticleMaking API calls exactly once when using WorkflowsGooglehttps://cloud.google.com/blog/products/application-development/using-single-execution-calls-with-workflows/Randy SpruytWorkflows Team LeadMete AtamelCloud Developer AdvocateScalable multi-tenancy management with Config Sync and team scopeshttps://cloud.google.com/blog/products/containers-kubernetes/how-to-use-config-sync-team-scopes/<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Ensuring application and service teams have the resources they need is crucial for platform administrators. </span><a href="https://cloud.google.com/anthos/fleet-management/docs/team-management"><span style="text-decoration: underline; vertical-align: baseline;">Fleet team management</span></a><span style="vertical-align: baseline;"> features in Google Kubernetes Engine (GKE) make this easier, allowing each team to function as a separate “tenant” within a fleet. In conjunction with </span><a href="https://cloud.google.com/anthos-config-management/docs/config-sync-overview"><span style="text-decoration: underline; vertical-align: baseline;">Config Sync</span></a><span style="vertical-align: baseline;">, a GitOps service in GKE, platform administrators can streamline resource management for their teams across the fleet.</span></p>
+<p><span style="vertical-align: baseline;">Specifically, with Config Sync team scopes, platform admins can define fleet-wide and team-specific cluster configurations such as resource quotas and network policies, allowing each application team to manage their own workloads within designated namespaces across clusters.</span></p>
+<p><span style="vertical-align: baseline;">Let's walk through a few scenarios.</span></p>
+<h3><strong style="vertical-align: baseline;">Separating resources for frontend and backend teams</strong></h3>
+<p><span style="vertical-align: baseline;">Let's say you need to provision resources for frontend and backend teams, each requiring their own tenant space. Using team scopes and fleet namespaces, you can control which teams access specific namespaces on specific member clusters.</span></p>
+<p><span style="vertical-align: baseline;">For example, the backend team might access their </span><code style="vertical-align: baseline;">bookstore</code><span style="vertical-align: baseline;"> and </span><code style="vertical-align: baseline;">shoestore</code><span style="vertical-align: baseline;"> namespaces on </span><code style="vertical-align: baseline;">us-east-cluster</code><span style="vertical-align: baseline;"> and </span><code style="vertical-align: baseline;">us-west-cluster</code><span style="vertical-align: baseline;"> clusters, while the frontend team has their </span><code style="vertical-align: baseline;">frontend-a</code><span style="vertical-align: baseline;"> and </span><code style="vertical-align: baseline;">frontend-b</code><span style="vertical-align: baseline;"> namespaces on all three member clusters.</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/1_-_intro.max-1000x1000.jpg"
+
+ alt="1 - intro">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><strong style="vertical-align: baseline;">Unlocking Dynamic Resource Provisioning with Config Sync<br/></strong><span style="vertical-align: baseline;">You can enable Config Sync by default at the fleet level using Terraform. Here’s a sample Terraform configuration:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'resource "google_gke_hub_feature" "feature" {\r\n name = "configmanagement"\r\n location = "global"\r\n provider = google\r\n fleet_default_member_config {\r\n configmanagement {\r\n config_sync {\r\n source_format = "unstructured"\r\n git {\r\n sync_repo = "https://github.com/GoogleCloudPlatform/anthos-config-management-samples"\r\n sync_branch = "main"\r\n policy_dir = "fleet-tenancy/config"\r\n secret_type = "none"\r\n }\r\n }\r\n }\r\n }\r\n}'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc89155b0>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="font-style: italic; vertical-align: baseline;">Note: Fleet defaults are only applied to new clusters created in the fleet.</span></p>
+<p><span style="vertical-align: baseline;">This Terraform configuration enables Config Sync as a </span><a href="https://cloud.google.com/anthos/fleet-management/docs/manage-features#configure_fleet-level_defaults"><span style="text-decoration: underline; vertical-align: baseline;">default fleet-level feature</span></a><span style="vertical-align: baseline;">. It installs Config Sync and instructs it to fetch Kubernetes manifests from a </span><a href="https://github.com/GoogleCloudPlatform/anthos-config-management-samples/tree/main/fleet-tenancy/config" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Git repository</span></a><span style="vertical-align: baseline;"> (specifically, the “main” branch and the “fleet-tenancy/config” folder). This configuration automatically applies to all clusters subsequently created within the fleet. This approach offers a powerful way of configuring manifests across fleet clusters without the need for manual installation and configuration on individual clusters.</span></p>
+<p><span style="vertical-align: baseline;">Now that you’ve configured Config Sync as a default fleet setting, you might want to sync specific Kubernetes resources to designated namespaces and clusters for each team. Integrating Config Sync with team scopes streamlines this process.</span></p>
+<p><strong style="vertical-align: baseline;">Setting team scope</strong><span style="vertical-align: baseline;"> <br/></span><span style="vertical-align: baseline;">Following this example, let’s assume you want to apply a different network policy for the backend team compared to the frontend team. Fleet team management features simplify the process of provisioning and managing infrastructure resources for individual teams, treating each team as a separate “tenant” within the fleet. </span></p>
+<p><span style="vertical-align: baseline;">To manage separate tenancy, as shown in the above team scope diagram, first </span><a href="https://cloud.google.com/anthos/fleet-management/docs/setup-teams"><span style="text-decoration: underline; vertical-align: baseline;">set up team scopes</span></a><span style="vertical-align: baseline;"> for the backend and frontend teams. This involves defining fleet-level namespaces and adding fleet member clusters to each team scope.</span></p>
+<p><span style="vertical-align: baseline;">Now, let's dive into those Kubernetes manifests that Config Sync syncs into the clusters.</span></p>
+<p><strong style="vertical-align: baseline;">Applying team scope in Config Sync<br/></strong><span style="vertical-align: baseline;">Each </span><a href="https://cloud.google.com/anthos/fleet-management/docs/team-management#fleet_team_management_overview"><span style="text-decoration: underline; vertical-align: baseline;">fleet namespace</span></a><span style="vertical-align: baseline;"> in the cluster is automatically labeled with </span><code style="vertical-align: baseline;">fleet.gke.io/fleet-scope: <scope name></code><span style="vertical-align: baseline;">. For example, the backend team scope contains the fleet namespaces </span><code style="vertical-align: baseline;">bookstore</code><span style="vertical-align: baseline;"> and </span><code style="vertical-align: baseline;">shoestore</code><span style="vertical-align: baseline;">, both labeled with </span><code style="vertical-align: baseline;">fleet.gke.io/fleet-scope: backend</code><span style="vertical-align: baseline;">. </span></p>
+<p><span style="vertical-align: baseline;">Config Sync's </span><a href="https://cloud.google.com/anthos-config-management/docs/how-to/namespace-scoped-objects#namespaceselectors_in_unstructured_repositories"><code style="text-decoration: underline; vertical-align: baseline;">NamespaceSelector</code></a><span style="vertical-align: baseline;"> utilizes this label to target specific namespaces within a team scope. Here's the configuration for the backend team:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'apiVersion: configmanagement.gke.io/v1\r\nkind: NamespaceSelector\r\nmetadata:\r\n name: backend-scope\r\nspec:\r\n mode: dynamic\r\n selector:\r\n matchLabels:\r\n fleet.gke.io/fleet-scope: backend'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc8915970>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><strong style="vertical-align: baseline;">Applying NetworkPolicies for the backend team<br/></strong><span style="vertical-align: baseline;">By annotating resources with </span><code style="vertical-align: baseline;">configmanagement.gke.io/namespace-selector: <NamespaceSelector name></code><span style="vertical-align: baseline;">, they're automatically applied to the right namespaces. Here’s the </span><code style="vertical-align: baseline;">NetworkPolicy</code><span style="vertical-align: baseline;"> of the backend team:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'apiVersion: networking.k8s.io/v1\r\nkind: NetworkPolicy\r\nmetadata:\r\n name: be-deny-all\r\n annotations:\r\n configmanagement.gke.io/namespace-selector: backend-scope\r\nspec:\r\n ingress:\r\n - from:\r\n - podSelector: {}\r\n podSelector:\r\n matchLabels: null'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc8915160>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">This </span><code style="vertical-align: baseline;">NetworkPolicy</code><span style="vertical-align: baseline;"> is automatically provisioned in the backend team's </span><code style="vertical-align: baseline;">bookstore</code><span style="vertical-align: baseline;"> and </span><code style="vertical-align: baseline;">shoestore</code><span style="vertical-align: baseline;"> namespaces, adapting to fleet changes like adding or removing namespaces and member clusters.</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/2_-_add_networkpolicy.max-1000x1000.jpg"
+
+ alt="2 - add networkpolicy">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><strong style="vertical-align: baseline;">Extending the concept: ResourceQuotas for the frontend team<br/></strong><span style="vertical-align: baseline;">Here's how a </span><code style="vertical-align: baseline;">ResourceQuota</code><span style="vertical-align: baseline;"> is dynamically applied to the frontend team's namespaces:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'apiVersion: configmanagement.gke.io/v1\r\nkind: NamespaceSelector\r\nmetadata:\r\n name: frontend-scope\r\nspec:\r\n mode: dynamic\r\n selector:\r\n matchLabels:\r\n fleet.gke.io/fleet-scope: frontend\r\n---\r\nkind: ResourceQuota\r\napiVersion: v1\r\nmetadata:\r\n name: fe-quota\r\n annotations:\r\n configmanagement.gke.io/namespace-selector: frontend-scope\r\nspec:\r\n hard:\r\n persistentvolumeclaims: "6"'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc8915310>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Similarly, this </span><code style="vertical-align: baseline;">ResourceQuota</code><span style="vertical-align: baseline;"> targets the frontend team's </span><code style="vertical-align: baseline;">frontend-a</code><span style="vertical-align: baseline;"> and </span><code style="vertical-align: baseline;">frontend-b</code><span style="vertical-align: baseline;"> namespaces, dynamically adjusting as the fleet's namespaces and member clusters evolve.</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/3_-_add_resourcequota.max-1000x1000.jpg"
+
+ alt="3 - add resourcequota">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><strong style="vertical-align: baseline;">Delegating resource management with Config Sync: Empowering the backend team<br/></strong><span style="vertical-align: baseline;">To allow the backend team to manage their own resources within their designated </span><code style="vertical-align: baseline;">bookstore</code><span style="vertical-align: baseline;"> namespace, you can use Config Sync's </span><a href="https://cloud.google.com/anthos-config-management/docs/reference/rootsync-reposync-fields"><code style="text-decoration: underline; vertical-align: baseline;">RepoSync</code></a><span style="vertical-align: baseline;">, and a slightly different </span><code style="vertical-align: baseline;">NamespaceSelector</code><span style="vertical-align: baseline;">.</span></p>
+<p><strong style="vertical-align: baseline;">Targeting a specific fleet namespace<br/></strong><span style="vertical-align: baseline;">To zero in on the backend team's </span><code style="vertical-align: baseline;">bookstore</code><span style="vertical-align: baseline;"> namespace, the following </span><code style="vertical-align: baseline;">NamespaceSelector</code><span style="vertical-align: baseline;"> targets both the team scope and the namespace name by labels:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'apiVersion: configmanagement.gke.io/v1\r\nkind: NamespaceSelector\r\nmetadata:\r\n name: backend-bookstore\r\nspec:\r\n mode: dynamic\r\n selector:\r\n matchLabels:\r\n fleet.gke.io/fleet-scope: backend\r\n kubernetes.io/metadata.name: bookstore'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc8915280>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><strong style="vertical-align: baseline;">Introducing RepoSync<br/></strong><span style="vertical-align: baseline;">Another Config Sync feature is </span><code style="vertical-align: baseline;">RepoSync</code><span style="vertical-align: baseline;">, which lets you delegate resource management within a specific namespace. For security reasons, </span><code style="vertical-align: baseline;">RepoSync</code><span style="vertical-align: baseline;"> has no default access; you must explicitly grant the necessary RBAC permissions to the namespace.</span></p>
+<p><span style="vertical-align: baseline;">Leveraging the </span><code style="vertical-align: baseline;">NamespaceSelector</code><span style="vertical-align: baseline;">, the following </span><code style="vertical-align: baseline;">RepoSync</code><span style="vertical-align: baseline;"> resource and its respective </span><code style="vertical-align: baseline;">RoleBinding</code><span style="vertical-align: baseline;"> can be applied dynamically to all </span><code style="vertical-align: baseline;">bookstore</code><span style="vertical-align: baseline;"> namespaces across the backend team's member clusters. The </span><code style="vertical-align: baseline;">RepoSync</code><span style="vertical-align: baseline;"> points it to a repository owned by the backend team:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'kind: RepoSync\r\napiVersion: configsync.gke.io/v1beta1\r\nmetadata:\r\n name: repo-sync\r\n annotations:\r\n configmanagement.gke.io/namespace-selector: backend-bookstore\r\nspec:\r\n sourceFormat: unstructured\r\n git:\r\n repo: https://github.com/GoogleCloudPlatform/anthos-config-management-samples\r\n branch: main\r\n dir: fleet-tenancy/teams/backend/bookstore\r\n auth: none\r\n---\r\nkind: RoleBinding\r\napiVersion: rbac.authorization.k8s.io/v1\r\nmetadata:\r\n name: be-bookstore\r\n annotations:\r\n configmanagement.gke.io/namespace-selector: backend-bookstore\r\nsubjects:\r\n- kind: ServiceAccount\r\n name: ns-reconciler-bookstore\r\n namespace: config-management-system\r\nroleRef:\r\n kind: ClusterRole\r\n name: admin\r\n apiGroup: rbac.authorization.k8s.io'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc8915be0>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="font-style: italic; vertical-align: baseline;">Note: The </span><code style="font-style: italic; vertical-align: baseline;">.spec.git</code><span style="font-style: italic; vertical-align: baseline;"> section would reference the backend team's repository.</span></p>
+<p><span style="vertical-align: baseline;">The backend team’s repository contains a </span><code style="vertical-align: baseline;">ConfigMap</code><span style="vertical-align: baseline;">. Config Sync ensures that the </span><code style="vertical-align: baseline;">ConfigMap</code><span style="vertical-align: baseline;"> is applied to the </span><code style="vertical-align: baseline;">bookstore</code><span style="vertical-align: baseline;"> namespaces across all backend team’s member clusters, supporting a GitOps approach to management.</span></p>
+<h3><strong style="vertical-align: baseline;">Easier cross-team resource management</strong></h3>
+<p><span style="vertical-align: baseline;">Managing resources across multiple teams within a fleet of clusters can be complex. Google Cloud's fleet team management features, combined with Config Sync, provide an effective solution to streamline this process.</span></p>
+<p><span style="vertical-align: baseline;">In this blog, we explored a scenario with frontend and backend teams, each requiring their own tenant spaces and resources (</span><code style="vertical-align: baseline;">NetworkPolicies</code><span style="vertical-align: baseline;">, </span><code style="vertical-align: baseline;">ResourceQuotas</code><span style="vertical-align: baseline;">, </span><code style="vertical-align: baseline;">RepoSync</code><span style="vertical-align: baseline;">). Using Config Sync in conjunction with the fleet management features, we automated the provisioning of these resources, helping to ensure a consistent and scalable setup.</span></p>
+<p><strong style="vertical-align: baseline;">Next steps</strong></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Learn how to </span><a href="https://cloud.google.com/anthos-config-management/docs/how-to/fleet-tenancy"><span style="text-decoration: underline; vertical-align: baseline;">use Config Sync to sync Kubernetes resources to team scopes and namespaces</span></a><span style="vertical-align: baseline;">.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">To experiment with this setup, visit the </span><a href="https://github.com/GoogleCloudPlatform/anthos-config-management-samples/tree/main/fleet-tenancy" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">example repository</span></a><span style="vertical-align: baseline;">. Config Sync configuration settings are located within the </span><a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/gke_hub_feature#nested_config_sync" rel="noopener" target="_blank"><code style="text-decoration: underline; vertical-align: baseline;">config_sync</code><span style="text-decoration: underline; vertical-align: baseline;"> block</span></a><span style="vertical-align: baseline;"> of the Terraform </span><code style="vertical-align: baseline;">google_gke_hub_feature</code><span style="vertical-align: baseline;"> resource.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">For simplicity, this example uses a public Git repository. To use a private repository, </span><a href="https://cloud.google.com/anthos-config-management/docs/how-to/installing-config-sync#git-creds-secret"><span style="text-decoration: underline; vertical-align: baseline;">create a Secret</span></a><span style="vertical-align: baseline;"> in each cluster to store authentication credentials.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">To learn more about Config Sync, see </span><a href="https://cloud.google.com/anthos-config-management/docs/config-sync-overview"><span style="text-decoration: underline; vertical-align: baseline;">Config Sync overview</span></a><span style="vertical-align: baseline;">.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">To learn more about fleets, see </span><a href="https://cloud.google.com/kubernetes-engine/fleet-management/docs" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;"><span style="text-decoration: underline; vertical-align: baseline;">Fleet management overview</span></a><span style="vertical-align: baseline;">.</span></p>
+</li>
+</ul></div>Fri, 03 May 2024 16:00:00 +0000https://cloud.google.com/blog/products/containers-kubernetes/how-to-use-config-sync-team-scopes/Management ToolsDevOps & SREContainers & KubernetesarticleScalable multi-tenancy management with Config Sync and team scopesGooglehttps://cloud.google.com/blog/products/containers-kubernetes/how-to-use-config-sync-team-scopes/Janet KuoStaff Software Engineer, Google CloudKavitha GowdaProduct Manager, Google CloudSimplifying data modeling and schema generation in BigQuery using multi-modal LLMshttps://cloud.google.com/blog/products/data-analytics/how-to-use-an-llm-to-create-data-schemas-in-bigquery/<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">The intricate hierarchical data structures in data warehouses and lakes sourced from diverse origins can make data modeling a protracted and error-prone process. To quickly adapt and create data models that meet evolving business requirements without having to rework them excessively, you need data models that are flexible, modular and adaptable enough to accommodate many requirements. This requires advanced technologies, proficient personnel, and robust methodologies.</span></p>
+<p><span style="vertical-align: baseline;">The advancements in generative AI offer numerous opportunities to address these challenges. Multimodal large language models (LLMs) can analyze examples of data in the data lake, including text descriptions, code, and even images of existing databases. By understanding this data and its relationships, LLMs can suggest or even automatically generate schema layouts, simplifying the laborious process of implementing the data model within the database, so developers can focus on higher value data management tasks.</span></p>
+<p><span style="vertical-align: baseline;">In this blog, we walk you through how to use multimodal LLMs in BigQuery to create a database schema. To do so, we’ll take a real-world example of entity relationship (ER) diagrams and examples of data definition languages (DDLs), and create a database schema in three steps. </span></p>
+<p><span style="vertical-align: baseline;">For this demonstration, we will use Data Beans, a fictional technology company built on BigQuery that provides a SaaS platform to coffee sellers. Data Beans leverages BigQuery’s integration with Vertex AI to access Google AI models like Gemini Vision Pro 1.0 to analyze unstructured data and integrate it with structured data, while using BigQuery to help with data modeling and generating insights. </span></p>
+<h3><strong style="vertical-align: baseline;">STEP1 : Create an entity relationship diagram </strong></h3>
+<p><span style="vertical-align: baseline;">The first step is to create an ER diagram using your favorite modeling tool, or to take a screenshot of an existing ER diagram. The ER diagram can contain primary key and foreign key relationships, and will then be used as an input to the Gemini Vision Pro 1.0 model to create relevant BigQuery DDLs.</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/image1_DfJ9Xwj.max-1000x1000.png"
+
+ alt="image1">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><h3><strong style="vertical-align: baseline;">STEP2 : Create a prompt with the ER image as input</strong></h3>
+<p><span style="vertical-align: baseline;">Next, </span><span style="vertical-align: baseline;">to create the DDL statements in BigQuery, </span><span style="vertical-align: baseline;">w</span><span style="vertical-align: baseline;">rite a prompt to take an ER image as an input. The prompt should include detailed and relevant rules that the Gemini model should follow. In addition, make sure the prompt captures learnings from the previous iterations — in other words, be sure to update your prompt as you experiment and iterate it. These can be provided as examples to the model, for example a valid schema description for BigQuery. Providing a working example for the model to follow will help the model create a data definition DDL that follows your desired rules. </span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', '## Prompt to guide the model\r\nllm_erd_prompt=f"""Use BigQuery SQL commands to create the following:\r\n- Create a new BigQuery schema named "{dataset_id}".\r\n- Use only BigQuery data types. Double and triple check this since it causes a lot of errors.\r\n- Create the BigQuery DDLs for the attached ERD.\r\n- Create primary keys for each table using the ALTER command. Use the "NOT ENFORCED" keyword.\r\n- Create foreign keys for each table using the ALTER command. Use the "NOT ENFORCED" keyword.\r\n- For each field add an OPTIONS for the description.\r\n- Cluster the table by the primary key.\r\n- For columns that can be null do not add "NULL" to the created SQL statement. BigQuery leaves this blank.\r\n- All ALTER TABLE statements should be at the bottom of the generated script.\r\n- The ALTER TABLE statements should be ordered by the primary key statements and then the foreign key statements. Order matters!\r\n- Double check your work especially that you used ONLY BigQuery data types.\r\n\r\n\r\nPrevious Errors that have been generated by this script. Be sure to check your work to avoid encountering these.\r\n- Query error: Type not found: FLOAT at [6:12]\r\n- Query error: Table test.company does not have Primary Key constraints at [25:1]\r\n\r\n\r\n## Example for model to influence from\r\nExample:\r\nCREATE TABLE IF NOT EXISTS `{project_id}.{dataset_id}.customer`\r\n(\r\n customer_id INTEGER NOT NULL OPTIONS(description="Primary key. Customer table."),\r\n country_id INTEGER NOT NULL OPTIONS(description="Foreign key: Country table."),\r\n customer_llm_summary STRING NOT NULL OPTIONS(description="LLM generated summary of customer data."),\r\n customer_lifetime_value STRING NOT NULL OPTIONS(description="Total sales for this customer."),\r\n customer_cluster_id FLOAT NOT NULL OPTIONS(description="Clustering algorithm id."),\r\n customer_review_llm_summary STRING OPTIONS(description="LLM summary are all of the customer reviews."),\r\n customer_survey_llm_summary STRING OPTIONS(description="LLM summary are all of the customer surveys.")\r\n)\r\nCLUSTER BY customer_id;\r\n\r\n\r\nCREATE TABLE IF NOT EXISTS `{project_id}.{dataset_id}.country`\r\n(\r\ncountry_id INTEGER NOT NULL OPTIONS(description="Primary key. Country table."),\r\ncountry_name STRING NOT NULL OPTIONS(description="The name of the country.")\r\n)\r\nCLUSTER BY country_id;\r\n\r\n\r\n\r\n\r\nALTER TABLE `{project_id}.{dataset_id}.customer` ADD PRIMARY KEY (customer_id) NOT ENFORCED;\r\nALTER TABLE `{project_id}.{dataset_id}.country` ADD PRIMARY KEY (country_id) NOT ENFORCED;\r\n\r\n\r\nALTER TABLE `{project_id}.{dataset_id}.customer` ADD FOREIGN KEY (country_id) REFERENCES `{project_id}.{dataset_id}.country`(country_id) NOT ENFORCED;\r\n"""'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc9189100>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Now you have an image of an ER diagram to present to your LLM.</span></p>
+<h3><strong style="vertical-align: baseline;">STEP 3: Call the Gemini Pro 1.0 Vision model </strong></h3>
+<p><span style="vertical-align: baseline;">After creating a prompt in Step 2, you are now ready to call the Gemini Pro 1.0 Vision model to generate the output by using the image of your ER diagram as an input (left side of Figure 1). You can do this in a number of ways — either directly from Colab notebooks using Python, or through BigQuery ML, leveraging its integration with Vertex AI: </span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'imageBase64 = convert_png_to_base64(menu_erd_filename)\r\n\r\n\r\nllm_response = GeminiProVisionLLM(llm_erd_prompt, imageBase64, temperature=.2, topP=1, topK=32)'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc9189190>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><h3><strong style="vertical-align: baseline;">Conclusions and resources</strong></h3>
+<p><span style="vertical-align: baseline;">In this demonstration, we saw how the multimodal Gemini model can streamline the creation of data and schemas. And while manually writing prompts is fine, it can be a daunting task when you need to do it at enterprise scale to create thousands of assets such as DDLs. Leveraging the above process, you can parameterize and automate prompt generation, dramatically speeding up the workflow and providing consistency across thousands of generated artifacts. You can find the complete Colab Enterprise notebook source code </span><a href="https://github.com/GoogleCloudPlatform/data-beans/blob/main/colab-enterprise/gen-ai-demo/Menu-Synthetic-Data-Generation-GenAI.ipynb" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">here</span></a><span style="vertical-align: baseline;">.</span></p>
+<p><span style="vertical-align: baseline;">BigQuery ML includes many new features to let you use Gemini Pro capabilities; for more, please see the </span><a href="https://cloud.google.com/bigquery/docs/reference/standard-sql/bigqueryml-syntax-generate-text"><span style="text-decoration: underline; vertical-align: baseline;">documentation</span></a><span style="vertical-align: baseline;">.</span><span style="vertical-align: baseline;"> Then, check out </span><span style="vertical-align: baseline;">this </span><a href="https://www.brighttalk.com/webcast/20069/600727?utm_source=GoogleCloud&utm_medium=brighttalk&utm_campaign=600727" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">tutorial</span></a><span style="vertical-align: baseline;"> to learn how to apply Google's models to your data, deploy models, and operationalize ML workflows — all without ever moving your data from BigQuery</span><span style="vertical-align: baseline;">. Finally, </span><span style="vertical-align: baseline;">for a behind-the-scenes look on how we made this demo, watch this video on </span><a href="https://www.youtube.com/watch?v=7zmPRPhWSGA" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">how to build an end-to-end data analytics and AI application</span></a><span style="vertical-align: baseline;"> using advanced models like Gemini directly from BigQuery.</span></p>
+<hr/>
+<p><sup><span style="font-style: italic; vertical-align: baseline;">Googlers Luis Velasco, Navjot Singh, Skander Larbi and Manoj Gunti contributed to this blog post. Many Googlers contributed to make these features a reality</span></sup></p></div>Fri, 03 May 2024 16:00:00 +0000https://cloud.google.com/blog/products/data-analytics/how-to-use-an-llm-to-create-data-schemas-in-bigquery/AI & Machine LearningData AnalyticsarticleSimplifying data modeling and schema generation in BigQuery using multi-modal LLMsGooglehttps://cloud.google.com/blog/products/data-analytics/how-to-use-an-llm-to-create-data-schemas-in-bigquery/Adam PaternostroTechnical Lead, Google CloudFirat TekinerSenior Staff Product Manager, Google CloudIntroducing Dataflux Dataset for Cloud Storage to accelerate PyTorch AI traininghttps://cloud.google.com/blog/products/ai-machine-learning/introducing-new-pytorch-dataflux-dataset-abstraction/<div class="block-paragraph_advanced"><h3><strong style="vertical-align: baseline;">Introduction</strong></h3>
+<p><span style="vertical-align: baseline;">Machine learning (ML) models thrive on massive datasets, and fast data loading is key for cost-effective ML training. We recently launched a PyTorch Dataset abstraction, the </span><a href="https://github.com/GoogleCloudPlatform/dataflux-pytorch" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Dataflux Dataset</span></a><span style="vertical-align: baseline;">, for accelerating data loading from Google’s Cloud Storage. Dataflux provides up to 3.5x faster training times compared to fsspec, with small files. </span></p>
+<p><span style="vertical-align: baseline;">Today’s launch builds upon Google’s commitment to open standards that spans over two decades of OSS contributions like TensorFlow, JAX, TFX, MLIR, KubeFlow, and Kubernetes, as well as sponsorship for critical OSS data science initiatives like Project Jupyter and NumFOCUS. </span></p>
+<p><span style="vertical-align: baseline;">We also validated the Dataflux Dataset on </span><a href="https://github.com/argonne-lcf/dlio_benchmark" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Deep Learning IO (DLIO) benchmarks</span></a><span style="vertical-align: baseline;"> and realized similar performance gains, even with larger files. Due to this broad performance boost, we recommend using Dataflux Dataset over other libraries or direct Cloud Storage API calls for training workflows.</span></p>
+<p><span style="vertical-align: baseline;">Key Dataflux Dataset features include:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Direct Cloud Storage integration:</strong><span style="vertical-align: baseline;"> Eliminate the need to download data locally first.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Performance optimization:</strong><span style="vertical-align: baseline;"> Achieve up to 3.5x faster training times, especially with small files. </span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">PyTorch Dataset primitive:</strong><span style="vertical-align: baseline;"> Work seamlessly with familiar PyTorch concepts.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Checkpointing support:</strong><span style="vertical-align: baseline;"> Save and load model checkpoints directly to/from Cloud Storage.</span></p>
+</li>
+</ul>
+<h3><strong style="vertical-align: baseline;">Using Dataflux Datasets</strong></h3>
+<ol>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Prerequisites:</strong><span style="vertical-align: baseline;"> Python 3.8+</span></p>
+</li>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Installation: </strong><strong style="vertical-align: baseline;">$ </strong><code style="vertical-align: baseline;">pip install gcs-torch-dataflux</code></p>
+</li>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Authentication:</strong><span style="vertical-align: baseline;"> Use Google Cloud </span><a href="https://cloud.google.com/docs/authentication/provide-credentials-adc"><span style="text-decoration: underline; vertical-align: baseline;">application-default authentication</span></a></p>
+</li>
+</ol>
+<p><strong style="vertical-align: baseline;">Example: Loading images for training</strong></p>
+<p><span style="vertical-align: baseline;">There are only a few changes needed to enable the Dataflux Dataset. </span><span style="vertical-align: baseline;">If you’re using PyTorch and have data in Cloud Storage, you most likely have written your own Dataset implementation. The below snippet shows how easy it is to create a Dataflux Dataset. For further details, checkout our </span><a href="https://github.com/GoogleCloudPlatform/dataflux-pytorch/tree/main" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">GitHub</span></a><span style="vertical-align: baseline;"> page.</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'import numpy\r\nimport io\r\nfrom PIL import Image\r\nfrom dataflux_pytorch import dataflux_mapstyle_dataset\r\n\r\ndef transform(img_in_bytes): \r\n return numpy.asarray(\r\nImage.open(io.BytesIO(img_in_bytes)))\r\n\r\ndataset = dataflux_mapstyle_dataset.DatafluxMapStyleDataset(\r\n project_name=PROJECT_NAME,\r\n bucket_name=BUCKET_NAME,\r\n config=dataflux_mapstyle_dataset.Config(prefix=PREFIX),\r\n data_format_fn=transform,\r\n)\r\n\r\n# Use "dataset" as usual in your ML-Training loop in combination with PyTorch DataLoader.'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc84b2f70>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><h3><strong style="vertical-align: baseline;">Under the hood</strong></h3>
+<p><span style="vertical-align: baseline;">To achieve such significant performance gains for Dataflux, we addressed the data-loading performance bottlenecks in ML training workflows. In a training run, data is loaded in batches from storage, and after some processing, is sent from CPU to GPU for ML-Training computations. If reading and constructing a batch takes longer than GPU computation, then the GPU is effectively stalled and underutilized, leading to longer training times.</span></p>
+<p><span style="vertical-align: baseline;">When data is in a cloud-based object storage system (like Google’s Cloud Storage), it takes longer to fetch the data than from a local disk, especially if the data is in small objects. This is due to time-to-first-byte latency. Once an object is ‘opened’ though, the cloud storage platform provides high throughput. In Dataflux, we employ a Cloud Storage feature called </span><a href="https://cloud.google.com/storage/docs/composing-objects"><span style="text-decoration: underline; vertical-align: baseline;">Compose Objects</span></a><span style="vertical-align: baseline;"> that can dynamically combine many smaller objects into a larger object. Then, instead of fetching (say) 1024 small objects (batch size), we only fetch 30 larger objects and download those to memory. The larger objects are then decomposed back to their individual smaller objects and served back as the dataset-samples. Any temporary composed objects created in the process are also cleaned up.</span></p>
+<p><span style="vertical-align: baseline;">Another optimization that Dataflux Datasets employs is high-throughput parallel-listing, speeding up the initial metadata needed for the dataset. Dataflux uses a sophisticated algorithm called work-stealing to significantly speed up listings; with it, even the first AI training run, or “epoch,” is faster compared to Dataflux Datasets without parallel-listing, even on datasets that have tens of millions of objects. </span></p>
+<p><span style="vertical-align: baseline;">Together, fast-listing and dynamic-composition help ensure that ML-training with Dataflux leads to minimal GPU stalls, leading to greatly reduced training time and increased accelerator utilization.</span></p>
+<p><span style="vertical-align: baseline;">Fast-listing and dynamic-composition are part of the </span><a href="https://github.com/GoogleCloudPlatform/dataflux-client-python" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Dataflux Client Libraries</span></a><span style="vertical-align: baseline;"> and available on </span><a href="https://github.com/GoogleCloudPlatform/dataflux-pytorch/tree/main" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">GitHub</span></a><span style="vertical-align: baseline;">. Dataflux Dataset uses these client libraries under the hood.</span></p>
+<h3><strong style="vertical-align: baseline;">Dataflux is available now</strong></h3>
+<p><span style="vertical-align: baseline;">Give the </span><a href="https://github.com/GoogleCloudPlatform/dataflux-pytorch/tree/main" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Dataflux Dataset for PyTorch</span></a><span style="vertical-align: baseline;"> (or the </span><a href="https://github.com/GoogleCloudPlatform/dataflux-client-python" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Dataflux Python client library</span></a><span style="vertical-align: baseline;"> if writing your own ML training dataset code) a try and </span><a href="mailto:dataflux-customer-support@google.com"><span style="text-decoration: underline; vertical-align: baseline;">let us know</span></a><span style="vertical-align: baseline;"> how it boosts your workflows! </span></p>
+<p><span style="vertical-align: baseline;">You can learn more about this and our other storage AI related capabilities from our Google Cloud Next ‘24 recorded session “How to define a storage infrastructure for AI and analytical workloads”</span></p></div>
+<div class="block-video">
+
+
+
+<div class="article-module article-video ">
+ <figure>
+ <a class="h-c-video h-c-video--marquee"
+ href="https://youtube.com/watch?v=A4daQj9tnWk"
+ data-glue-modal-trigger="uni-modal-A4daQj9tnWk-"
+ data-glue-modal-disabled-on-mobile="true">
+
+
+ <img src="//img.youtube.com/vi/A4daQj9tnWk/maxresdefault.jpg"
+ alt="How to define a storage infrastructure for AI and analytical workloads"/>
+
+ <svg role="img" class="h-c-video__play h-c-icon h-c-icon--color-white">
+ <use xlink:href="#mi-youtube-icon"></use>
+ </svg>
+ </a>
+
+
+ </figure>
+</div>
+
+<div class="h-c-modal--video"
+ data-glue-modal="uni-modal-A4daQj9tnWk-"
+ data-glue-modal-close-label="Close Dialog">
+ <a class="glue-yt-video"
+ data-glue-yt-video-autoplay="true"
+ data-glue-yt-video-height="99%"
+ data-glue-yt-video-vid="A4daQj9tnWk"
+ data-glue-yt-video-width="100%"
+ href="https://youtube.com/watch?v=A4daQj9tnWk"
+ ng-cloak>
+ </a>
+</div>
+
+</div>Thu, 02 May 2024 16:00:00 +0000https://cloud.google.com/blog/products/ai-machine-learning/introducing-new-pytorch-dataflux-dataset-abstraction/Developers & PractitionersAI & Machine LearningarticleIntroducing Dataflux Dataset for Cloud Storage to accelerate PyTorch AI trainingGooglehttps://cloud.google.com/blog/products/ai-machine-learning/introducing-new-pytorch-dataflux-dataset-abstraction/Mayur DeshpandeStaff Software EngineerAbhishek LalProduct Manager, Google CloudPrivate networking patterns to Vertex AI workloadshttps://cloud.google.com/blog/products/networking/private-connectivity-to-vertex-workloads/<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">As enterprise strategic use cases for AI adoption increases, secure and reliable connectivity is more crucial than ever. Get ready to explore several private connections options for your Vertex AI workloads! In this blog, we'll dive into the existing options and reveal the services to get you connected on your AI journey.</span></p>
+<h3><span style="vertical-align: baseline;">Connectivity matrix </span></h3>
+<p><a href="https://cloud.google.com/vertex-ai/docs/start/introduction-unified-platform"><span style="text-decoration: underline; vertical-align: baseline;">Vertex AI</span></a><span style="vertical-align: baseline;"> is a suite of products which provide different AI workloads that provide varying functionalities. The default method to access Vertex AI API’s are public which is the case with Google APIs in general. </span><span style="vertical-align: baseline;">Depending on your architecture you may have the requirement to access your API’s privately, because of security and enterprise governance, which means traffic does not travel over the internet to the public address of the API. In these cases there are several options which we will explore later in the blog but it will vary depending on the Vertex AI product you are connecting to. The image below shows the connectivity matrix for </span><a href="https://cloud.google.com/vertex-ai/docs/general/netsec-overview#support-table"><span style="text-decoration: underline; vertical-align: baseline;">accessing Vertex AI from on-premises and multicloud</span></a><span style="vertical-align: baseline;">.</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/1-matrix.max-1000x1000.png"
+
+ alt="1-matrix">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><h3><span style="vertical-align: baseline;">Options</span></h3>
+<p><span style="vertical-align: baseline;">As you can see from the previous matrix image there are several methods in addition to the public internet. These include:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><a href="https://cloud.google.com/vpc/docs/private-service-connect"><strong style="text-decoration: underline; vertical-align: baseline;">Private Service Connect</strong></a><strong style="vertical-align: baseline;"> (PSC) for Google APIs</strong><span style="vertical-align: baseline;"> - Provides private access to Google APIs over hybrid networking or within a Virtual Private Cloud (VPC) using a customer-specified IP address(s) and DNS endpoint name that can be leveraged for one or more use cases.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><a href="https://cloud.google.com/vpc/docs/private-google-access"><strong style="text-decoration: underline; vertical-align: baseline;">Private Google Access</strong></a><span style="vertical-align: baseline;"> - Provides private access to Google APIs over hybrid networking or within a Virtual Private Cloud (VPC) using a Google defined subnet.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><a href="https://cloud.google.com/vpc/docs/private-services-access"><strong style="text-decoration: underline; vertical-align: baseline;">Private Service Access</strong></a><strong style="vertical-align: baseline;"> (PSA) </strong><span style="vertical-align: baseline;">- Google and other providers, collectively known as "service providers," can offer services hosted within a Google-managed VPC network. PSA enables you to define IP addresses for the managed services in addition to establishing VPC peering to access the internal IP addresses of these Google and third-party services over hybrid networking or within the VPC.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Private Service Connect endpoint</strong><span style="vertical-align: baseline;"> - Enables consumers to securely access managed services hosted by Google or other providers from within their own Virtual Private Cloud (VPC) network or via hybrid networking, eliminating the need to define the producer's VPC network. Communication with managed services is established through PSC endpoints or backends defined by the consumer's IP space, facilitating multi-tenancy to producer services across VPCs.</span></p>
+</li>
+</ul>
+<h3><span style="vertical-align: baseline;">Example </span></h3>
+<p><span style="vertical-align: baseline;">The following diagram shows a Vector Search architecture in which the Vector Search API is enabled and managed in a service project (appropriately named "serviceproject") as part of a </span><a href="https://cloud.google.com/vpc/docs/shared-vpc"><span style="vertical-align: baseline;">Shared VPC</span></a><span style="vertical-align: baseline;"> deployment. The Vector Search Compute Engine resources are deployed as a Google-managed Infrastructure-as-a-Service (IaaS) in the service producer's VPC network.</span></p>
+<p><a href="https://cloud.google.com/vpc/docs/private-service-connect#endpoints"><span style="text-decoration: underline; vertical-align: baseline;">Private Service Connect endpoints</span></a><span style="vertical-align: baseline;"> are deployed in the consumer's VPC network (serviceproject) for index query, in addition to </span><a href="https://cloud.google.com/vertex-ai/docs/general/googleapi-access-methods#psc"><span style="text-decoration: underline; vertical-align: baseline;">Private Service Connect endpoints for Google APIs</span></a><span style="vertical-align: baseline;"> for private index creation deployed in the host project, the VPC where the cloud router resides. Both index creation and index query are accessible privately through hybrid networking or within the VPC. </span></p>
+<p><span style="vertical-align: baseline;">If the organization requires public access to index query, you can leverage the same producer service as a Private Service Connect Network Endpoint Groups </span><a href="https://cloud.google.com/load-balancing/docs/negs#psc-neg"><span style="text-decoration: underline; vertical-align: baseline;">(PSC NEG) </span></a><span style="vertical-align: baseline;">backend to a External Load Balancer, thereby enabling public access to the endpoint while also providing WAF and DDoS capabilities when associated with </span><a href="https://cloud.google.com/armor/docs/rule-tuning"><span style="text-decoration: underline; vertical-align: baseline;">Cloud Armor</span></a><span style="vertical-align: baseline;">.</span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/2-vertex-psc.max-1000x1000.png"
+
+ alt="2-vertex-psc">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><h3><span style="vertical-align: baseline;">Get hands-on and learn more</span></h3>
+<p><span style="vertical-align: baseline;">This topic is hot right now, and there are many approaches you can use. There are a few resources available that you can use to get some hands-on experience. Please check out the following tutorials.</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Tutorial</strong><span style="vertical-align: baseline;"> - </span><a href="https://cloud.google.com/vertex-ai/docs/general/vertex-psc-vector-search"><span style="text-decoration: underline; vertical-align: baseline;">Use Private Service Connect to access a Vector Search index from on-premises</span></a><span style="vertical-align: baseline;">.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Tutorial</strong><span style="vertical-align: baseline;"> - </span><a href="https://cloud.google.com/vertex-ai/docs/general/vertex-psc-gen-ai"><span style="text-decoration: underline; vertical-align: baseline;">Use Private Service Connect to access Generative AI on Vertex AI from on-premises</span></a><span style="vertical-align: baseline;">. </span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Tutorial</strong><span style="vertical-align: baseline;"> - </span><a href="https://cloud.google.com/vertex-ai/docs/general/vertex-psc-googleapis"><span style="text-decoration: underline; vertical-align: baseline;">Use Private Service Connect to access Vertex AI online predictions from on-premises</span></a></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Tutorial </strong><span style="vertical-align: baseline;">- </span><a href="https://cloud.google.com/vertex-ai/docs/general/vertex-psc-batch-predictions"><span style="text-decoration: underline; vertical-align: baseline;">Use Private Service Connect to access Vertex AI batch predictions from on-premises</span></a></p>
+</li>
+</ul>
+<p><span style="vertical-align: baseline;">To learn out more or share a thought find me on </span><a href="https://www.linkedin.com/in/ammett/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Linkedin</span></a>.</p></div>
+<div class="block-related_article_tout">
+
+
+
+
+
+<div class="uni-related-article-tout h-c-page">
+ <section class="h-c-grid">
+ <a href="https://cloud.google.com/blog/products/networking/connect-google-cloud-to-on-prem-and-other-clouds/"
+ data-analytics='{
+ "event": "page interaction",
+ "category": "article lead",
+ "action": "related article - inline",
+ "label": "article: {slug}"
+ }'
+ class="uni-related-article-tout__wrapper h-c-grid__col h-c-grid__col--8 h-c-grid__col-m--6 h-c-grid__col-l--6
+ h-c-grid__col--offset-2 h-c-grid__col-m--offset-3 h-c-grid__col-l--offset-3 uni-click-tracker">
+ <div class="uni-related-article-tout__inner-wrapper">
+ <p class="uni-related-article-tout__eyebrow h-c-eyebrow">Related Article</p>
+
+ <div class="uni-related-article-tout__content-wrapper">
+ <div class="uni-related-article-tout__image-wrapper">
+ <div class="uni-related-article-tout__image" style="background-image: url('https://storage.googleapis.com/gweb-cloudblog-publish/images/networking_3Z7Xc6t.max-500x500.jpg')"></div>
+ </div>
+ <div class="uni-related-article-tout__content">
+ <h4 class="uni-related-article-tout__header h-has-bottom-margin">Cross-Cloud Network: Private, customizable and flexible networking</h4>
+ <p class="uni-related-article-tout__body">Explore the Cross-Cloud Network architecture ebook and learn how Google’s global scale network can support your enterprise multicloud and...</p>
+ <div class="cta module-cta h-c-copy uni-related-article-tout__cta muted">
+ <span class="nowrap">Read Article
+ <svg class="icon h-c-icon" role="presentation">
+ <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#mi-arrow-forward"></use>
+ </svg>
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </a>
+ </section>
+</div>
+
+</div>Thu, 02 May 2024 16:00:00 +0000https://cloud.google.com/blog/products/networking/private-connectivity-to-vertex-workloads/Hybrid & MulticloudDevelopers & PractitionersNetworkingarticlePrivate networking patterns to Vertex AI workloadshttps://storage.googleapis.com/gweb-cloudblog-publish/images/0-ai-hero.max-600x600.pngGooglehttps://cloud.google.com/blog/products/networking/private-connectivity-to-vertex-workloads/Ammett WilliamsDeveloper Relations EngineerDeepak MichaelNetworking Specialist Customer EngineerRAG in production faster with Ray, LangChain and HuggingFacehttps://cloud.google.com/blog/products/ai-machine-learning/rag-quickstart-with-ray-langchain-and-huggingface/<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">We’re excited to announce the release of a </span><a href="https://console.cloud.google.com/marketplace/product/google/rag-on-gke" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">quickstart solution</span></a><span style="vertical-align: baseline;"> and </span><a href="https://github.com/GoogleCloudPlatform/ai-on-gke/tree/main/applications/rag#rag-on-gke-application" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">reference architecture</span></a><span style="vertical-align: baseline;"> for retrieval augmented generation (RAG) applications, designed to accelerate your journey to production. In this post, you’ll learn how to quickly deploy a complete RAG application on </span><a href="https://cloud.google.com/kubernetes-engine?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Google Kubernetes Engine</span></a><span style="vertical-align: baseline;"> (GKE), and </span><a href="https://cloud.google.com/sql/docs/postgres"><span style="text-decoration: underline; vertical-align: baseline;">Cloud SQL for PostgreSQL</span></a><span style="vertical-align: baseline;"> and </span><a href="https://github.com/pgvector/pgvector" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">pgvector</span></a><span style="vertical-align: baseline;">, using Ray, LangChain, and Hugging Face.</span></p>
+<h3><strong style="vertical-align: baseline;">What is RAG?</strong></h3>
+<p><span style="vertical-align: baseline;">RAG can improve the outputs of foundation modes, such as large language models (LLMs), for a specific application. Rather than relying purely on knowledge developed during training, AI apps equipped for RAG can retrieve the information most relevant to a user’s prompt from an external knowledge base, then add that information to the prompt before sending it to the generative model. The knowledge base can come in various forms, such as a vector database, traditional search index, or relational database — and by accessing it, customer service chabots can look up help center articles, digital shopping assistants can tap into product catalogs and customer reviews, and AI-powered travel agents can deliver up-to-date flight and hotel information. </span></p></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/1_RAG_Conceptual_Diagram_FINAL.max-1000x1000.png"
+
+ alt="1 RAG Conceptual Diagram FINAL">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">LLMs rely on their training data, which can quickly fall out of date and may not include data relevant to the application’s domain. Re-training or fine-tuning an LLM to provide fresh, domain-specific data can be an expensive and complex process. RAG not only gives the LLM access to such data without training or-fine tuning. but can also guide an LLM toward factual responses, thereby reducing hallucinations and enabling applications to provide human-verifiable source material. </span></p>
+<p><span style="vertical-align: baseline;">For more background on how RAG works, see our blog on </span><a href="https://cloud.google.com/blog/products/ai-machine-learning/context-aware-code-generation-rag-and-vertex-ai-codey-apis"><span style="text-decoration: underline; vertical-align: baseline;">context-aware code generation</span></a><span style="vertical-align: baseline;">.</span></p>
+<h3><strong style="vertical-align: baseline;">AI Infrastructure for RAG</strong></h3>
+<p><span style="vertical-align: baseline;">Prior to the rise of Generative AI, a typical application architecture might involve a database, a set of microservices, and a frontend. Even the most basic RAG applications introduce new requirements for serving LLMs, processing, and retrieving unstructured data. To meet these requirements, customers need infrastructure that is optimized specifically for AI workloads. </span></p>
+<p><span style="vertical-align: baseline;">Many customers choose to access AI infrastructure like TPUs and GPUs via a fully managed platform, such as </span><a href="https://cloud.google.com/vertex-ai?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Vertex AI</span></a><span style="vertical-align: baseline;">. Others, however, prefer to manage their own infrastructure on top of GKE while leveraging open-source frameworks and open models. This blog post is for the latter group. </span></p>
+<p><span style="vertical-align: baseline;">Building an AI platform from scratch involves a number of key decisions, such as which frameworks to use for model serving, which machine shapes to use for inference, how to protect sensitive data, how to meet cost and performance requirements, and how to scale as traffic grows. Each decision involves many tradeoffs against a vast and fast-changing landscape of generative AI tools.</span></p>
+<p><span style="vertical-align: baseline;">This is why we have developed a quickstart solution and reference architecture for RAG applications built on top of GKE, Cloud SQL, and open-source frameworks </span><a href="https://www.ray.io/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Ray</span></a><span style="vertical-align: baseline;">, </span><a href="https://www.langchain.com/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">LangChain</span></a><span style="vertical-align: baseline;"> and </span><a href="https://huggingface.co/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Hugging Face</span></a><span style="vertical-align: baseline;">. Our solution is designed to help you get started quickly and accelerate your journey to production with RAG best practices built-in from the start.</span></p>
+<h3><strong style="vertical-align: baseline;">Benefits of RAG on GKE and Cloud SQL</strong></h3>
+<p><span style="vertical-align: baseline;">GKE and Cloud SQL accelerate your journey to production in a variety of ways:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Load Data Fast</strong><span style="vertical-align: baseline;"> - Use </span><a href="https://docs.ray.io/en/latest/data/data.html" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Ray Data</span></a><span style="vertical-align: baseline;"> to seamlessly access data in parallel from your Ray cluster via GKE’s </span><a href="https://cloud.google.com/kubernetes-engine/docs/how-to/persistent-volumes/cloud-storage-fuse-csi-driver"><span style="text-decoration: underline; vertical-align: baseline;">GCSFuse driver</span></a><span style="vertical-align: baseline;">. Efficiently load your embeddings into </span><a href="https://cloud.google.com/sql/docs/postgres"><span style="text-decoration: underline; vertical-align: baseline;">Cloud SQL for PostgreSQL</span></a><span style="vertical-align: baseline;"> and </span><a href="https://github.com/pgvector/pgvector" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">pgvector</span></a><span style="vertical-align: baseline;"> to perform low latency vector search at scale.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Fast deploy</strong><span style="vertical-align: baseline;"> - Quickly deploy Ray, </span><a href="https://jupyter.org/hub" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">JupyterHub</span></a><span style="vertical-align: baseline;">, and Hugging Face </span><a href="https://huggingface.co/docs/text-generation-inference/en/index" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Text Generation Inference</span></a><span style="vertical-align: baseline;"> (TGI) to your GKE cluster</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Security made simple</strong><span style="vertical-align: baseline;"> - Get </span><a href="https://cloud.google.com/blog/products/containers-kubernetes/move-in-ready-kubernetes-security-with-gke-autopilot"><span style="text-decoration: underline; vertical-align: baseline;">move-in ready Kubernetes security</span></a><span style="vertical-align: baseline;"> with </span><a href="https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-overview"><span style="text-decoration: underline; vertical-align: baseline;">GKE</span></a><span style="vertical-align: baseline;">. Filter out sensitive or toxic content using </span><a href="https://cloud.google.com/sensitive-data-protection/docs/sensitive-data-protection-overview"><span style="text-decoration: underline; vertical-align: baseline;">Sensitive Data Protection</span></a><span style="vertical-align: baseline;"> (SDP). Leverage Google-standard authentication with </span><a href="https://cloud.google.com/security/products/iap?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Identity-Aware Proxy</span></a><span style="vertical-align: baseline;"> so users can seamlessly connect to your LLM frontend and Jupyter notebooks.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Cost efficiency & reduced management overhead</strong><span style="vertical-align: baseline;"> - GKE reduces cluster maintenance and makes it easy to take advantage of cost-saving measures like </span><a href="https://cloud.google.com/kubernetes-engine/docs/concepts/spot-vms"><span style="text-decoration: underline; vertical-align: baseline;">spot nodes</span></a><span style="vertical-align: baseline;"> via YAML configuration.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Scalability -</strong><span style="vertical-align: baseline;"> GKE </span><a href="https://cloud.google.com/kubernetes-engine/docs/concepts/cluster-autoscaler"><span style="text-decoration: underline; vertical-align: baseline;">automatically</span></a><span style="vertical-align: baseline;"> provisions nodes as traffic grows, eliminating the need for manual configuration to scale up.</span></p>
+</li>
+</ul>
+<h3><strong style="vertical-align: baseline;">Deploying RAG on GKE and Cloud SQL</strong></h3>
+<p><span style="vertical-align: baseline;">Our end-to-end </span><a href="https://github.com/GoogleCloudPlatform/ai-on-gke/tree/main/applications/rag" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">RAG application</span></a><span style="vertical-align: baseline;"> and </span><a href="https://github.com/GoogleCloudPlatform/ai-on-gke/tree/main/applications/rag#rag-on-gke-application" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">reference architecture</span></a><span style="vertical-align: baseline;"> provide the following:</span></p>
+<ol>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Google Cloud project </strong><span style="vertical-align: baseline;">- configures your project with the needed prerequisites to run the RAG application, including a GKE Cluster and Cloud SQL for PostgreSQL and pgvector instance</span></p>
+</li>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">AI frameworks</strong><span style="vertical-align: baseline;"> - deploys Ray, JupyterHub, and Hugging Face TGI to GKE</span></p>
+</li>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">RAG Embedding Pipeline</strong><span style="vertical-align: baseline;"> - generates embeddings and populates the Cloud SQL for PostgreSQL and pgvector instance</span></p>
+</li>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Example RAG Chatbot Application</strong><span style="vertical-align: baseline;"> - deploys a web-based RAG chatbot to GKE</span></p>
+</li>
+</ol></div>
+<div class="block-image_full_width">
+
+
+
+
+
+
+
+ <div class="article-module h-c-page">
+ <div class="h-c-grid">
+
+
+ <figure class="article-image--large
+
+
+ h-c-grid__col
+ h-c-grid__col--6 h-c-grid__col--offset-3
+
+
+ "
+ >
+
+
+
+
+ <img
+ src="https://storage.googleapis.com/gweb-cloudblog-publish/images/2_RAG_High_Level_Architecture.max-1000x1000.png"
+
+ alt="2 RAG High Level Architecture">
+
+ </a>
+
+ </figure>
+
+
+ </div>
+ </div>
+
+
+
+
+
+</div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">The example chatbot application provides a web interface where users can interact with an open source LLM. It leverages data loaded by the RAG data pipeline into Cloud SQL for PostgreSQL with pgvector, providing more comprehensive and informative responses to user queries. </span></p>
+<p><span style="vertical-align: baseline;">Our end-to-end RAG solution serves as a starting point for further development, demonstrating the potential of this technology for a wide range of applications. By combining the power of RAG with the scalability and flexibility of GKE and Cloud SQL as well as security features of Google Cloud, developers can build powerful and versatile applications that can handle complex tasks and provide valuable insights. </span></p>
+<p><span style="vertical-align: baseline;">We plan to evolve this solution over time, including the ability to add custom data sets, replace models, and update the dataset and vector database with new documents.</span></p>
+<p><span style="vertical-align: baseline;">For more information, please check our </span><a href="https://github.com/GoogleCloudPlatform/ai-on-gke/blob/main/applications/rag/README.md" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">README</span></a><span style="vertical-align: baseline;"> and </span><a href="https://github.com/GoogleCloudPlatform/ai-on-gke/tree/main/applications/rag" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">github instructions</span></a><span style="vertical-align: baseline;">, and </span><a href="https://cloud.google.com/architecture/rag-capable-gen-ai-app-using-gke"><span style="text-decoration: underline; vertical-align: baseline;">reference RAG architecture</span></a><span style="vertical-align: baseline;">. You can also </span><a href="https://www.youtube.com/watch?v=qwFCZKKFXd4" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">view our Google Cloud Next 2024 session</span></a><span style="vertical-align: baseline;"> discussing RAG.</span></p></div>Thu, 02 May 2024 16:00:00 +0000https://cloud.google.com/blog/products/ai-machine-learning/rag-quickstart-with-ray-langchain-and-huggingface/Containers & KubernetesAI & Machine LearningarticleRAG in production faster with Ray, LangChain and HuggingFaceGooglehttps://cloud.google.com/blog/products/ai-machine-learning/rag-quickstart-with-ray-langchain-and-huggingface/Julie AmundsonSenior Staff Software EngineerJason Soo HooSoftware Engineering ManagerSullivan County debuts generative AI chatbot, Saige, to answer constituent FAQshttps://cloud.google.com/blog/topics/public-sector/sullivan-county-debuts-generative-ai-chatbot-saige-to-answer-constituent-faqs/<div class="block-paragraph"><p data-block-key="6t5sl">Sullivan County, New York, is home to the Catskills Mountains. It’s a great place to live, play, and raise a family, and we have a robust group of visitors and tourists. We are also a fairly small county. Being on the cutting edge of technology isn’t typically something people associate with local governments, and I’m proud of Sullivan County for consistently innovating.</p><p data-block-key="5cguk">Traditionally, in offices like ours, our teams are routinely answering rote questions about operating hours or document filing processes. These calls take up hours of their day they’d like to spend helping solve more complex problems. In 2023, we introduced a virtual agent powered by <a href="https://cloud.google.com/dialogflow">Dialogflow</a> that has helped us quickly provide our constituents with answers to simple questions. We embedded the agent into our chatbot on the <a href="https://www.sullivanny.us/" target="_blank">county website</a> to support those seeking information about our County Clerk’s and Treasurer’s offices.</p><p data-block-key="enceg">With the chatbot’s support, we’ve seen a 62% reduction in call volume. This has allowed our teams to focus on resolving more complex issues. The success of that rollout attracted the attention of the other offices in the county, and we saw a chance to expand our chatbot’s capabilities.</p><h3 data-block-key="eeoeu"><b>Simplifying generative AI with Vertex AI to overhaul a chatbot in 10 weeks</b></h3><p data-block-key="fh15p">Although more than 40 offices in Sullivan County were excited to implement a chatbot, we were initially concerned about the time and effort it would take to tackle a project of that scale. Some leaders assumed that many chatbots would require manually combing through information on office websites and building chatbot workflows for each of them. Then, I was introduced to <a href="https://cloud.google.com/vertex-ai-search-and-conversation?hl=en">Vertex AI Agent Builder</a>. Vertex AI Agent Builder makes it easy, even for our nontechnical teams, to train machine learning models that grow and change over time. Since it can “learn,” we can create chatbots that scrape information from the respective office sites and dynamically determine the best answer to a question on any given day. We don’t have to design any of those flows manually.</p><p data-block-key="6an9e">My team worked with Google Cloud Premier Partner <a href="https://quantiphi.com/partners/google-cloud/" target="_blank">Quantiphi</a> to implement a generative AI-powered version of our virtual agent (who we call Saige), and their enthusiasm about the project was palpable. The project was completed and connected every department in the county in just ten weeks, thanks to the support from Quantiphi.</p><h3 data-block-key="14gjh"><b>Improving interactions with constituents as Saige learns over time</b></h3><p data-block-key="36rus">I grew up tinkering with computers in the 1980s, and I’ve been told my entire life that computers will make our lives easier, but training people on new technologies is often cumbersome and complicated. I believe that if a task using technology is more difficult or time-consuming than doing it manually, no one will adopt that new tool. With Vertex AI, I’m seeing technology make good on its promise to improve lives.</p><p data-block-key="dki4l">We’ve already seen Saige grow and evolve to make our jobs easier. As it gathered information from various department sites, it helped us identify sources that needed to be updated. If it responds to a question incorrectly, I can click “This was not helpful,” and ask the question again. Saige is able to search for and find new information immediately. This is especially valuable because information changes; holidays change operating hours or a file is updated, and our small teams don’t have time to manually update every chatbot workflow.</p><p data-block-key="3cqu9">As Saige’s knowledge repository grows, our offices continue to get more and more time back to manage more complex issues that require the face-to-face, human touch. Our offices get more efficient, people get answers faster, and every interaction we have with a constituent helps inform the next.</p><h3 data-block-key="9ieoq"><b>Setting new goals for an AI-powered Sullivan County</b></h3><p data-block-key="5br2l">Hearing about new experiences from our teams and the people of Sullivan County is one thing, and it’s another to be able to truly measure impact. We’ve implemented a <a href="https://cloud.google.com/looker?hl=en">Looker</a> dashboard that is helping us track exactly how much impact our chat features have on our offices. I can easily view total user sessions, success rates of chat interactions, and peak hours, so we can refine our support to best meet our community’s needs.</p><p data-block-key="duhoq">I can also see what questions people are asking, which helps me to understand what subjects are trending. Gathering experiential data alongside quantifiable data helps us offer better services and information about popular topics, in more prominent places, on our websites.</p><p data-block-key="4bmd7">When I think of the future of Sullivan County’s online resources, I think about what I would want as a constituent coming to our sites for information. As our chat function continues to improve over time, I’d love to offer additional services directly through chat, such as payments or form submissions. All of these tools can come together to further augment our amazing staff and provide Sullivan County constituents with the best possible service.</p><p data-block-key="5rhn3">Interested in seeing how the state of New York is transforming ? Learn more about <a href="https://papers.govtech.com/How-GenAI-is-Transforming-Public-Sector-Services-in-New-York-142886.html?" target="_blank">how gen AI is transforming public sector services in New York</a>.</p></div>Thu, 02 May 2024 16:00:00 +0000https://cloud.google.com/blog/topics/public-sector/sullivan-county-debuts-generative-ai-chatbot-saige-to-answer-constituent-faqs/Public SectorarticleSullivan County debuts generative AI chatbot, Saige, to answer constituent FAQshttps://storage.googleapis.com/gweb-cloudblog-publish/images/GCPNA009-002---Sullivan-County_siWv7DA.max-600x600.jpgGooglehttps://cloud.google.com/blog/topics/public-sector/sullivan-county-debuts-generative-ai-chatbot-saige-to-answer-constituent-faqs/Dan HustDirector of CommunicationsSullivan CountyAI can be the catalyst to reignite your digital transformationhttps://cloud.google.com/blog/products/application-modernization/register-for-building-apps-in-an-ai-era-webinar/<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Be honest with me: Is your “digital transformation” stuck? Did you start in earnest a few years back, and now you’re sitting on half-finished projects, uneven outcomes, and a distracted staff? It happens. Maintaining momentum for multi-year efforts isn’t easy. Especially efforts that are increasingly broad and complex! We need a catalyst to focus our efforts, motivate our teams, and simplify our work. </span><strong style="vertical-align: baseline;">Early signals tell us that generative AI is that missing catalyst, and Google Cloud is a unique partner for your journey.</strong></p>
+<h3><span style="vertical-align: baseline;">How you got stuck</span></h3>
+<p><span style="vertical-align: baseline;">Digital transformation means many things to many people. Is it about becoming more efficient? Upgrading tools? Delivering new digital products to customers? Adopting a data-driven strategy? Changing internal culture? </span><a href="https://cloud.google.com/blog/transform/the-meaning-of-digital-transformation-is-changing"><span style="text-decoration: underline; vertical-align: baseline;">All of those things</span></a><span style="vertical-align: baseline;">? We don’t always see a unifying purpose to these efforts that’s capable of rallying an organization. This lack of focus often results in a dizzying array of disparate projects. </span></p>
+<p><span style="vertical-align: baseline;">Some of these projects are focused on new customer experiences. You might have tried launching new mobile or web experiences with solid, but not spectacular, results. There are always a handful of backend projects initiated to adopt public cloud, establish a real-time data infrastructure, set up developer-friendly application platforms, and upgrade security services. This inevitably sparks modernization programs to make data more accessible, apps more scalable, and infrastructure more automated. Smart companies complement these technology efforts with promises to invest in a company culture that </span><a href="https://dora.dev/devops-capabilities/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">embraces modern thinking and elite capabilities</span></a><span style="vertical-align: baseline;">.</span></p>
+<p><span style="vertical-align: baseline;">None of those are bad things! But sometimes they come with unintended consequences:</span></p>
+<ul>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">More complex infrastructure that straddles public cloud and private cloud</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Legacy systems straining under load and change rates that they weren’t designed for</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Regularly changing measures of success, from innovation to cost savings to optimization to efficiencies</span></p>
+</li>
+<li aria-level="1" style="list-style-type: disc; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Team demotivation, as this growing bag of projects seems increasingly disconnected from measurable outcomes</span></p>
+</li>
+</ul>
+<p><span style="vertical-align: baseline;">There’s a better way. In our experience, a corporate investment in generative AI brings focus, meaning, and acceleration to a host of important IT efforts.</span></p>
+<h3><span style="vertical-align: baseline;">Why generative AI catalyzes your team</span></h3>
+<p><span style="vertical-align: baseline;">A business strategy with generative AI at the center benefits customers and employees. Why? For customers, it helps focus your attention on delivering more personalized and engaging experiences. There are </span><a href="https://cloud.google.com/transform/101-real-world-generative-ai-use-cases-from-industry-leaders"><span style="text-decoration: underline; vertical-align: baseline;">at least 101 examples of that</span></a><span style="vertical-align: baseline;">. For staff, it puts a spotlight on how everyone can use smarter tools to design, deliver, and operate products — whether those are data reports, software applications, or infrastructure platforms. Everyone gets to join in!</span></p>
+<p><span style="vertical-align: baseline;">And that’s the thing. It’s not just about generative AI; it’s about what it takes to be </span><span style="font-style: italic; vertical-align: baseline;">good</span><span style="vertical-align: baseline;"> at generative AI. Everyone needs to come together to fully commit to excellence in five supporting areas (that were usually left half-finished during a classic digital transformation):</span></p>
+<ol>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Automate your infrastructure</strong><span style="vertical-align: baseline;">. Now’s the time to establish a full range of automation for provisioning, upgrading, and deleting all of the machinery that supports your (AI-hosting) infrastructure.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Upgrade your data platform</strong><span style="vertical-align: baseline;">. Your AI models won’t be any good without good data. Timely, accurate data is critical, and that means investing in flexible data pipelines, scalable databases, and a data warehouse that’s ready for AI.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Improve your developer experience</strong><span style="vertical-align: baseline;">. To build with AI, your developers need the tools, frameworks, and platform services that help them iterate quickly. It’s also time to finish those cultural upgrades that unleash your teams.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Modernize your security practices</strong><span style="vertical-align: baseline;">. Embracing generative AI requires a whole set of data, application, and infrastructure security considerations. You won’t deploy it if you don’t trust it. It’s key to make the necessary upgrades to your security posture.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">Finish your cloud migration</strong><span style="vertical-align: baseline;">. It’s going to be hard to maximize the value of generative AI outside of the public cloud. Places like Google Cloud are purpose-built to support the access to innovation, elasticity, and scale that are so important right now.</span></p>
+</li>
+</ol>
+<h3><span style="vertical-align: baseline;">What you need to succeed</span></h3>
+<p><span style="vertical-align: baseline;">Looking to avoid some of the challenges of past transformations? There’s more than one way to proceed with your generative AI strategy, but at Google Cloud, we see three crucial building blocks for your success.</span></p>
+<p><span style="vertical-align: baseline;">You need </span><strong style="vertical-align: baseline;">proximity</strong><span style="vertical-align: baseline;">. Generative AI models and apps require proximity to dependent data. From AlloyDB to BigQuery, Google Cloud’s data services give you the speed, scale, and price performance to keep your AI-based systems grounded by your unique information. And especially now, you need </span><strong style="vertical-align: baseline;">proximity to expertise</strong><span style="vertical-align: baseline;"> for your journey. This is a period of excitement and change, so you want Google’s world-class team partnering with you to help you architect, deliver, and optimize your AI-based solutions.</span></p>
+<p><span style="vertical-align: baseline;">You need an </span><strong style="vertical-align: baseline;">integrated AI platform</strong><span style="vertical-align: baseline;">. This isn’t the time for building out complex, brittle, do-it-yourself AI platforms. Too much is evolving too quickly. Buy innovation and flexibility, not complexity. Our </span><a href="https://cloud.google.com/blog/products/compute/whats-new-with-google-clouds-ai-hypercomputer-architecture"><span style="text-decoration: underline; vertical-align: baseline;">unique AI hypercomputer</span></a><span style="vertical-align: baseline;">, </span><a href="https://cloud.google.com/vertex-ai"><span style="text-decoration: underline; vertical-align: baseline;">Vertex AI platform for MLOps</span></a><span style="vertical-align: baseline;">, and </span><a href="https://cloud.google.com/products/gemini"><span style="text-decoration: underline; vertical-align: baseline;">Gemini for Google Cloud</span></a><span style="vertical-align: baseline;"> offer best-in-class vertical and horizontal integrations that help you build, run, and optimize better than anywhere else.</span></p>
+<p><span style="vertical-align: baseline;">Finally, you need cross-organization </span><strong style="vertical-align: baseline;">productivity assistance</strong><span style="vertical-align: baseline;">. AI is not just about different output; it’s about a different way of working. </span><a href="https://workspace.google.com/solutions/ai/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Gemini for Google Workspace</span></a><span style="vertical-align: baseline;"> helps everyone be more creative and productive. </span><a href="https://cloud.google.com/products/gemini/code-assist"><span style="text-decoration: underline; vertical-align: baseline;">Gemini Code Assist</span></a><span style="vertical-align: baseline;"> gives software developers powerful tools for understanding and writing quality software. </span><a href="https://cloud.google.com/products/gemini/cloud-assist"><span style="text-decoration: underline; vertical-align: baseline;">Gemini Cloud Assist</span></a><span style="vertical-align: baseline;"> will bring game-changing AI assistance to teams that need to troubleshoot and optimize their cloud systems.</span></p>
+<p><span style="vertical-align: baseline;">Ready to get unstuck? Register for our </span><a href="https://cloudonair.withgoogle.com/events/building-applications-in-the-ai-era?utm_source=google&utm_medium=blog&utm_campaign=FY24-Q2-global-Prod931-onlineevent-er-Building-Apps-in-the-AI-Era&utm_content=launch_blog&utm_term=-" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Building Apps in an AI Era webinar</span></a><span style="vertical-align: baseline;"> to learn more about how Google Cloud can help you innovate faster, deliver unparalleled customer experiences, and secure a lasting competitive advantage.</span></p></div>Thu, 02 May 2024 13:00:00 +0000https://cloud.google.com/blog/products/application-modernization/register-for-building-apps-in-an-ai-era-webinar/AI & Machine LearningApplication ModernizationarticleAI can be the catalyst to reignite your digital transformationGooglehttps://cloud.google.com/blog/products/application-modernization/register-for-building-apps-in-an-ai-era-webinar/Richard SeroterChief Evangelist, Google CloudYour modernization journey starts with the endpoint. A Forrester Consulting study shows why.https://cloud.google.com/blog/products/chrome-enterprise/your-modernization-journey-starts-with-the-endpoint-a-forrester-consulting-study-shows-why/<div class="block-paragraph"><p data-block-key="axxn5">In today’s digital age, endpoints are a business requirement for collaborating with coworkers, engaging with customers, and building great products. However, with a rise in cyber attacks, increased scrutiny on cost, and pressure to innovate, IT departments require a new kind of endpoint that improves user experience, simplifies management, increases security and reduces costs—which are some of the key traits of what we refer to as the modern endpoint.</p></div>
+<div class="block-paragraph"><p data-block-key="axxn5">We commissioned Forrester Consulting to survey 652 IT professionals to explore the meaning of a modern endpoint to IT departments, which Forrester further defines in the study as “a mix of multiple next-generation capabilities that center around artificial intelligence (AI), web-based applications, the cloud, and the integration of data.” <sup>1</sup></p></div>
+<div class="block-paragraph"><p data-block-key="pogf7">The study found that IT leaders are “prioritizing initiatives that lead to a modern endpoint.” In particular, the study found that “IT leaders are prioritizing AI, web-based applications, and endpoint management in the cloud because these initiatives are core to a modern endpoint and will allow businesses to evolve with their employees and customers needs.”<sup>1</sup></p><p data-block-key="4uh1f">Specific to AI, the study found that IT respondents' “number-one priority over the next 12 months is to enable end users to take advantage of AI on the endpoint.”<sup>1</sup> The study talks specifically to productivity gains for IT staff, who can use AI to “automate repetitive tasks, analyze data from endpoint devices and plan maintenance, or analyze user behavior to create more personalized computing experiences.” <sup>1</sup></p></div>
+<div class="block-paragraph"><p data-block-key="pogf7">Businesses starting their journey to a true modern endpoint should consider adopting ChromeOS. In this blog post, we’ll visit three of the four key findings from the Forrester Consulting study <a href="http://inthecloud.withgoogle.com/forrester-next-generation-endpoint-report/home.html" target="_blank">“Delivering the Next-Generation endpoint</a>,” and show how ChromeOS can help businesses realize their modern endpoint needs.</p></div>
+<div class="block-paragraph"><h3 data-block-key="pogf7"><b>1. Endpoint security, management, and deployment are the top barriers to a modern endpoint.</b></h3></div>
+<div class="block-paragraph"><p data-block-key="pogf7">In the study, Forrester consulting found that IT respondents indicated that they spent nearly half of their working hours on endpoint security (19%), management (15%), and deployment (14%).<sup>1</sup></p><p data-block-key="4qmts">ChromeOS can help IT departments reduce time securing, managing, and deploying devices. With regards to security, ChromeOS is built to be secure at every layer: at the lowest level, every ChromeOS device relies on Verified Boot which checks for tampering; second, every app and tab on ChromeOS is sandboxed, meaning each app has a clear perimeter in which it can operate; and third, by making the web the core application platform, apps are simply secure by design, with much more control over how they interact with powerful device features. This means that ransomware simply can't run on ChromeOS devices.*</p><p data-block-key="f99jj">The result? There has never been a successful ransomware or virus attack reported on ChromeOS devices—ever.*</p><p data-block-key="6t5mo">ChromeOS can be centrally managed alongside your other devices via the web-based Google Admin console. From there, IT administrators gain a comprehensive view, allowing them to monitor and manage devices, track application deployments and versions, and control device policies and settings at scale, with changes applied across the fleet in seconds. Additionally, admins can revoke user access and securely wipe data from devices when necessary.</p><p data-block-key="5lvbl">With zero-touch enrollment, it’s possible to deploy a fleet of ChromeOS devices without IT interaction. ChromeOS devices can be shipped directly to your end users, who can then get started in minutes—with policies, settings and apps all instantly applied on first boot as the user connects to the internet and signs in.</p></div>
+<div class="block-paragraph"><h3 data-block-key="pogf7"><b>2. Web applications are the key to a modern endpoint.</b></h3></div>
+<div class="block-paragraph"><p data-block-key="pogf7">While AI was identified as IT’s top priority, the study identified the second-highest priority over the next 12 months as the need to embrace more web-based applications, with 81% of respondents saying that “adopting web-based applications is part of their organization’s digital transformation goals.”<sup>1</sup> Forrester Consulting also found that 90% of surveyed IT respondents believe the future of end user computing is web-based and 78% of respondents indicated that companies that don’t embrace the web will be left behind.<sup>1</sup></p><p data-block-key="dk5q8">The study found that IT departments perceive web-based applications not only as collaboration drivers, but as beneficial for IT departments as well. Why? Quoted from the study, “When the majority of applications that employees use are web-based, it makes all other elements of endpoint management easier to achieve, from simplifying management and improving security to unlocking the power of AI.”<sup>1</sup> In addition to the security benefits mentioned previously, the web helps businesses streamline ecosystem support, access, and deployment.</p><p data-block-key="ahmuq">With <a href="http://support.google.com/chromebook/answer/9658361?hl=en&co=GENIE.Platform%3DDesktop" target="_blank">progressive web apps</a>, key software partnerships featured in <a href="http://chromeos.google/resources/recommended/" target="_blank">Chrome Enterprise Recommended</a>, simple application management, and more, ChromeOS can be the catalyst for businesses to realize the benefits of the web.</p></div>
+<div class="block-paragraph"><h3 data-block-key="pogf7"><b>3. Achieving a modern endpoint benefits the business.</b></h3></div>
+<div class="block-paragraph"><p data-block-key="pogf7">Finally, let's talk about cost. Forrester Consulting found that moving towards a modern endpoint would reduce costs to the IT department by roughly 19%, with 57% believing it will help reduce costs for the IT department.<sup>1</sup> Modern endpoints help IT departments save beyond the endpoint—including infrastructure costs, security software, support costs, and more.</p><p data-block-key="cplpd">ChromeOS devices can help streamline IT, slashing overall costs beyond the hardware, saving businesses $463 per device on average according to IDC.<sup>2</sup> These savings carry over even when deploying <a href="http://www.google.com/chromebook/discover/chromebookplus/" target="_blank">Chromebook Plus</a>, a category of high performance laptops with powerful AI capabilities, and greater hardware specs at a greater value. Chromebook Plus comes with 10 years of automatic updates, staying secure and usable for even longer.</p><p data-block-key="a9jqt">Embracing a modern endpoint strategy with ChromeOS can solve the most pressing IT challenges faced today. Check out the <a href="http://inthecloud.withgoogle.com/forrester-next-generation-endpoint-report/home.html" target="_blank">Forrester Consulting Study</a> to learn more about the modern endpoint, or contact one of our team members to <a href="https://chromeos.google/contact/" target="_blank">learn more about ChromeOS.</a></p></div>
+<div class="block-paragraph"><p data-block-key="d62p6"><i><sup>1</sup></i> <a href="http://inthecloud.withgoogle.com/forrester-next-generation-endpoint-report/home.html" target="_blank"><sup>Forrester Consulting 2024 Modern Endpoint Research, sponsored by Google, April 2024</sup></a></p><p data-block-key="6h6da"><i><sup>2</sup></i> <a href="http://services.google.com/fh/files/misc/idc_business_value_of_chrome_os_paper.pdf" target="_blank"><i><sup>IDC Business Value Paper, sponsored by Google, The Business Value of ChromeOS, doc #49920522, March 2024</sup></i></a></p><p data-block-key="etj2b"><i><sup>*As of May 2024 there has been no evidence of any documented, successful virus attack or ransomware attack on ChromeOS. Data based on ChromeOS monitoring of various national and internal databases.</sup></i></p></div>Thu, 02 May 2024 09:00:00 +0000https://cloud.google.com/blog/products/chrome-enterprise/your-modernization-journey-starts-with-the-endpoint-a-forrester-consulting-study-shows-why/Chrome EnterprisearticleYour modernization journey starts with the endpoint. A Forrester Consulting study shows why.https://storage.googleapis.com/gweb-cloudblog-publish/images/2023_Wagtail_hero_template_2436x1200_0mwtXaa.max-600x600.jpgGooglehttps://cloud.google.com/blog/products/chrome-enterprise/your-modernization-journey-starts-with-the-endpoint-a-forrester-consulting-study-shows-why/Rob BeardProduct ManagerChromeOSMax KayenProduct Marketing ManagerChromeOSEnhancing iEEG seizure identification and similarity search with Google Cloudhttps://cloud.google.com/blog/products/databases/neuropace-scales-ml-workloads-with-vertex-ai/<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Globally, epilepsy affects approximately 50 million people. Located in Mountain View, CA, NeuroPace, Inc.<sup>1</sup></span><span style="vertical-align: baseline;"> is committed to transforming the lives of those living with epilepsy by reducing or eliminating their seizures. The company's RNS® System,<sup>2</sup></span><span style="vertical-align: baseline;"> a responsive neurostimulation device, monitors brain activity to detect seizure precursors and delivers targeted electrical stimulation to prevent seizures. This device also captures iEEG (intracranial electroencephalogram) data, with over 15 million recordings from over 5,000 patients collected to date, making it the largest collection of ambulatory iEEG records available. </span></p>
+<p><span style="vertical-align: baseline;">NeuroPace's AI team has developed electrographic seizure classifier models using clinical trial data from the RNS System and has fine-tuned these models through </span><a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC10354337/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">transfer learning</span></a><span style="vertical-align: baseline;"> to identify seizure onset times. Previously, machine learning (“ML”) training was constrained by the limited number of Graphical Processing Units (GPUs) available in on-premises virtual machines (VMs), slowing down the optimization of models and training processes. NeuroPace tackled this challenge by scaling ML workloads with Google Cloud, moving away from on-premises VMs and utilizing </span><a href="https://cloud.google.com/vertex-ai/?hl=en"><span style="text-decoration: underline; vertical-align: baseline;">Vertex AI</span></a><span style="vertical-align: baseline;"> for more efficient training and hyperparameter tuning.</span></p>
+<h3><span style="vertical-align: baseline;">Leveraging Google Cloud AI infrastructure</span></h3>
+<p><span style="vertical-align: baseline;">Google Cloud's technologies have significantly improved and accelerated NeuroPace’s ML training capabilities. Searching through more than a million iEEG records to identify similar ones, a task that previously took minutes to hours, can now be completed in milliseconds using Google's </span><a href="https://cloud.google.com/alloydb/ai"><span style="text-decoration: underline; vertical-align: baseline;">AlloyDB AI</span></a><span style="vertical-align: baseline;">, part of the </span><a href="https://cloud.google.com/alloydb"><span style="text-decoration: underline; vertical-align: baseline;">AlloyDB for PostgreSQL</span></a><span style="vertical-align: baseline;"> database. Further, the integration of Vertex AI, GPUs, Compute Engine, and Google Cloud Storage has revolutionized NeuroPace’s ML training processes, enhancing scalability, automation, and efficiency.</span></p>
+<p><span style="vertical-align: baseline;">Vertex AI, Google Cloud’s AI development platform, supports the entire ML workflow, including data engineering, model training, deployment, and monitoring. This integration enables NeuroPace's AI team to use various GPUs for model training, with </span><a href="https://cloud.google.com/blog/products/compute/introducing-g2-vms-with-nvidia-l4-gpus"><span style="text-decoration: underline; vertical-align: baseline;">L4 GPUs</span></a><span style="vertical-align: baseline;"> offering better price-performance compared to on-premises resources. With it, they’ve developed a cloud-native ML training system, achieving desired scalability and efficiency through Vertex AI and GPUs.</span></p>
+<h3><span style="vertical-align: baseline;">Patient similarity search with AlloyDB AI</span></h3>
+<p><span style="vertical-align: baseline;">Identifying similar electrophysiological features across epilepsy patients has the potential to aid in discovering effective treatment options. NeuroPace has conducted research studies to identify similar iEEG patterns within a large dataset of over 1 million time-series iEEG records, utilizing the built-in vector search capabilities in AlloyDB AI. By employing IVFFlat and HNSW indexing methods, searches for similar iEEG records in this dataset can now be executed in approximately ten milliseconds.</span></p>
+<p><span style="vertical-align: baseline;">AlloyDB AI enables storing data embeddings in vector form directly in the database, facilitating easier and faster similarity searches compared to standard PostgreSQL. This eliminates the need for elaborate external processing pipelines.</span></p>
+<h3><span style="vertical-align: baseline;">The next-generation disease management system</span></h3>
+<p><span style="vertical-align: baseline;">Data captured from the NeuroPace RNS System may provide insights into seizure trends and triggers leading to optimizing and personalizing epilepsy treatment.<sup>3</sup></span><span style="vertical-align: baseline;"> The research efforts to integrate Google Cloud's infrastructure with NeuroPace's RNS System data are directed towards creating a sophisticated disease management system for epilepsy, emphasizing tailored treatments and enhanced patient well-being.</span></p>
+<hr/>
+<p><sup><em>1. <a href="https://www.neuropace.com/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">https://www.neuropace.com/</span></a></em></sup><br/><sup><em>2. <span style="vertical-align: baseline;">Rx Only. The RNS® System is an adjunctive therapy for adults with refractory, partial onset seizures with no more than 2 epileptogenic foci. See important safety information at </span><a href="http://www.neuropace.com/safety/" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">http://www.neuropace.com/safety/.</span></a></em></sup><br/><sup><em>3. <span style="vertical-align: baseline;">The RNS System does not currently incorporate functionality that is based upon or utilizes AI features.</span></em></sup></p></div>Wed, 01 May 2024 16:00:00 +0000https://cloud.google.com/blog/products/databases/neuropace-scales-ml-workloads-with-vertex-ai/CustomersDatabasesarticleEnhancing iEEG seizure identification and similarity search with Google CloudGooglehttps://cloud.google.com/blog/products/databases/neuropace-scales-ml-workloads-with-vertex-ai/Sharanya Desai, Ph.D.Technical Fellow, Director of AI, NeuroPace, Inc.Iris FangEnterprise Customer Engineer, Google CloudManaging Cloud Storage soft delete at scalehttps://cloud.google.com/blog/products/storage-data-transfer/understanding-cloud-storages-new-soft-delete-feature/<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Have you ever accidentally deleted your data? Unfortunately, many of us have, which is why most operating systems on personal computers have a recycle bin / trash can where you can go to get your files back. On the enterprise side, these accidental deletions can be at a much larger scale – sometimes involving millions or even billions of objects. There is also the prospect of someone gaining unauthorized access to your data and either performing a ransomware attack to try to hold your data hostage or simply deleting it!</span></p>
+<p><span style="vertical-align: baseline;">We recently launched </span><a href="https://cloud.google.com/storage/docs/soft-delete"><span style="text-decoration: underline; vertical-align: baseline;">soft delete</span></a><span style="vertical-align: baseline;"> for Cloud Storage, an important new data protection feature compatible with all existing Cloud Storage features and workloads. It offers improved protection against accidental and malicious data deletion by providing you with a way to retain and restore recently deleted data at enterprise scale. With soft delete in place, you may also find that your organization can move more quickly when “pruning” old data, knowing that soft delete provides an undo mechanism in case of any mistakes.</span></p>
+<p><span style="vertical-align: baseline;">In this blog, we provide you with the tools and insights you need to optimize your soft delete settings, even at scale, so that you use soft delete to protect your data based on its business criticality.</span></p>
+<h2><span style="vertical-align: baseline;">How does soft delete work and how is it billed?</span></h2>
+<p><span style="vertical-align: baseline;">When soft delete is enabled, deleted objects are retained in a hidden soft-deleted state for the soft delete retention duration set on that bucket, instead of being permanently deleted. If you need any of the soft-deleted objects back, simply run a restore and they are copied back to live state.</span></p>
+<p><span style="vertical-align: baseline;">We introduced soft delete with a seven-day retention duration enabled on all existing buckets and as the default for newly created buckets. Soft delete is on by default because accidental deletion events are unfortunately all too common and much of the data stored in Cloud Storage is business-critical in nature. In addition to the seven-day default, you can select any number of days between 7 and 90, or you can disable the feature entirely.</span></p>
+<p><span style="vertical-align: baseline;">Soft delete usage is billed based on the storage class of the recently deleted objects. In many cases, this only increases bills by a few percentage points, which hopefully represents a good value for the amount of protection that soft delete provides. However, enabling soft delete on buckets that contain a large amount of short-lived (frequently deleted) data can result in large billing increases, since an object deleted after an hour would be billed for the one hour the object was live, plus seven days of soft delete usage.</span></p>
+<h2><span style="vertical-align: baseline;">How valuable is your data?</span></h2>
+<p><span style="vertical-align: baseline;">In order to get to a state where soft delete protects you from data deletion risks that have the lowest economical impact, we recommend that you ask yourself the following three questions:</span></p>
+<ol>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">How important is my organization’s data?</strong><span style="vertical-align: baseline;"> Are we storing temporary objects or media transcodes that could be easily regenerated if they were lost? Soft delete protection is unlikely to be worth it in these cases. Or are we storing data that would put my business and/or customer relationships at risk if it were lost? Soft delete could provide a vital level of protection here.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">What level of data protection do we already have?</strong><span style="vertical-align: baseline;"> If Cloud Storage has the only copy of your business-critical data, then soft delete protection would be much more important than if you were storing long-term backups of all your data in another Google Cloud region, on-prem, or with another cloud provider.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><strong style="vertical-align: baseline;">How much data protection can we afford?</strong><span style="vertical-align: baseline;"> Soft delete can be much less expensive than performing traditional enterprise backups, but can still have a significant impact on billing, depending mostly on your deletion rates. We recommend considering the cost of soft delete relative to your overall Google Cloud bill rather than only storage because it is protecting your business data relied on by your overall workloads. You may find that leaving soft delete enabled on all your buckets only has a single digit percentage impact on your cloud bill, which may be worth it given the protection it provides against both accidental and malicious deletion events.</span></p>
+</li>
+</ol>
+<p><span style="vertical-align: baseline;">Once you have a good idea as to where and how much you want to use soft delete, the next steps depend on your architectural choices and the overall complexity of your organization’s cloud presence. For the rest of this blog, we’ll cover how to assess soft delete’s impact and act on that information, starting with bucket-level metrics, then acting on bucket-level settings within a project, using Terraform for management, and concluding with organizational-level management approaches.</span></p>
+<h2><span style="vertical-align: baseline;">Assessing bucket-level impacts</span></h2>
+<p><span style="vertical-align: baseline;">You can estimate bucket-level soft delete costs using </span><a href="https://cloud.google.com/monitoring/api/v3/metrics"><span style="text-decoration: underline; vertical-align: baseline;">Cloud Monitoring metrics</span></a><span style="vertical-align: baseline;"> and visualize them using the </span><a href="https://cloud.google.com/monitoring/charts/metrics-explorer"><span style="text-decoration: underline; vertical-align: baseline;">Metrics Explorer</span></a><span style="vertical-align: baseline;">. You might want to inspect a handful of buckets that are representative of different kinds of datasets to get a better idea of which ones are more and less expensive to protect with soft delete.</span></p>
+<h3><span style="vertical-align: baseline;">Storage metrics</span></h3>
+<p><span style="vertical-align: baseline;">Recently, we introduced </span><a href="https://cloud.google.com/monitoring/api/metrics_gcp#gcp-storage"><span style="text-decoration: underline; vertical-align: baseline;">new storage metrics</span></a><span style="vertical-align: baseline;"> that allow you to break down the object counts, bytes, and byte seconds by storage class, and then further by live vs. noncurrent vs. soft-deleted vs. multipart. These breakdowns can be extremely useful even beyond any soft delete analysis you may want to perform. In addition, you can now inspect the deletion rate using the new deleted_bytes metric:</span></p>
+<p><span style="vertical-align: baseline;">The </span><strong style="vertical-align: baseline;">storage/v2/deleted_bytes</strong><span style="vertical-align: baseline;"> metric is a delta count of deleted bytes per bucket, grouped by storage class. It can be used to estimate soft delete billing impact, even if soft delete is disabled or set to a different retention duration than the one being considered.</span></p>
+<p><span style="vertical-align: baseline;">For example, the absolute cost of soft delete can be calculated as follows: Soft delete retention duration × deleted bytes × </span><a href="https://cloud.google.com/storage/pricing"><span style="text-decoration: underline; vertical-align: baseline;">storage price</span></a><span style="vertical-align: baseline;">. For example, the cost (assuming us-central1 and Standard storage) of enabling a 7-day soft delete policy with 100,000 GB of deletions during the course of a month is (7 / 30.4375 days) × 100,000 GB × $0.02/GB mo = $459.96 (where 30.4375 is the average number of days per month).</span></p>
+<p><span style="vertical-align: baseline;">The relative cost of soft delete can also be calculated by comparing the </span><strong style="vertical-align: baseline;">storage/v2/deleted_bytes</strong><span style="vertical-align: baseline;"> metric to the existing </span><strong style="vertical-align: baseline;">storage/v2/total_byte_seconds</strong><span style="vertical-align: baseline;"> metric: soft delete retention duration × deleted bytes / total bytes. Continuing from the above example and given 1,000,000 GB-months of storage for the month, the relative cost of enabling soft delete in this case is: (7 / 30.4375 days) × 100,000 GB / 1,000,000 GB = 2.3% impact.</span></p>
+<h2><span style="vertical-align: baseline;">Metrics Explorer</span></h2>
+<p><span style="vertical-align: baseline;">You can use the </span><a href="https://cloud.google.com/monitoring/charts/metrics-explorer"><span style="text-decoration: underline; vertical-align: baseline;">Metrics Explorer</span></a><span style="vertical-align: baseline;"> to create charts that visualize estimated soft delete costs for a given bucket:</span></p>
+<ol>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">In the navigation panel of the Google Cloud console, select Monitoring, and then select Metrics explorer (</span><a href="https://pantheon.corp.google.com/monitoring/metrics-explorer" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">Go to Metrics explorer</span></a><span style="vertical-align: baseline;">).</span></p>
+</li>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Verify that </span><a href="https://cloud.google.com/monitoring/mql"><span style="text-decoration: underline; vertical-align: baseline;">MQL</span></a><span style="vertical-align: baseline;"> is selected in the Language toggle.</span></p>
+</li>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Enter the following query into the query editor:</span></p>
+</li>
+</ol></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', "{\r\n fetch gcs_bucket :: storage.googleapis.com/storage/v2/deleted_bytes\r\n | value val(0) * 604800.0's'\r\n | group_by [resource.bucket_name, metric.storage_class], window(), .sum;\r\n fetch gcs_bucket :: storage.googleapis.com/storage/v2/total_byte_seconds\r\n | filter metric.type != 'soft-deleted-object'\r\n | group_by [resource.bucket_name, metric.storage_class], window(1d), .mean\r\n | group_by [resource.bucket_name, metric.storage_class], window(), .sum\r\n}\r\n| every 30d\r\n| within 360d\r\n| ratio"), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc22f0070>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Note: This query assumes a 7-day (604,800 seconds) soft delete window.</span></p>
+<h2><span style="vertical-align: baseline;">Taking action within a project</span></h2>
+<p><span style="vertical-align: baseline;">If you are a storage administrator making decisions about soft delete settings within a project, you may want to go over your list of buckets manually and make decisions based on your business knowledge of what should be protected versus what can go without soft delete. For a larger number of buckets, you might choose to use the above metrics to generate a list of buckets that exceed a billing impact threshold (e.g. 20% impact) on all your buckets and then disable soft delete on those buckets.</span></p>
+<p><span style="vertical-align: baseline;">To assist with this, we published a </span><a href="https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/storage/cost-analysis" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">soft delete billing impact Python script</span></a><span style="vertical-align: baseline;"> on Github that generates a list of buckets in a project that exceed the percentage of billing impact that you specify, factoring in the storage classes of objects inside a bucket. The script can also be used to update the soft delete policies based on a specified relative cost threshold.</span></p>
+<p><span style="vertical-align: baseline;">We recommend you use the </span><a href="https://cloud.google.com/sdk/gcloud/"><span style="text-decoration: underline; vertical-align: baseline;">Google Cloud CLI</span></a><span style="vertical-align: baseline;"> to configure soft delete settings on one or more buckets within a project. After </span><a href="https://cloud.google.com/sdk/docs/install-sdk"><span style="text-decoration: underline; vertical-align: baseline;">installing</span></a><span style="vertical-align: baseline;"> and </span><a href="https://cloud.google.com/docs/authentication/gcloud"><span style="text-decoration: underline; vertical-align: baseline;">signing in</span></a><span style="vertical-align: baseline;">, the following </span><a href="https://cloud.google.com/sdk/gcloud/reference/storage"><span style="text-decoration: underline; vertical-align: baseline;">gcloud storage</span></a><span style="vertical-align: baseline;"> commands are examples of actions you may want to take to enable, update, or disable soft delete policies within a specified project:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', '# Set your project ID\r\n$ gcloud config set project $MY_PROJECT_ID\r\n\r\n# Disable Soft Delete on one bucket\r\n$ gcloud storage buckets update --clear-soft-delete gs://example-bucket\r\n\r\n# Disable Soft Delete on a list of buckets\r\n$ cat buckets.txt | gcloud storage buckets update -I --clear-soft-delete\r\n\r\n# Disable Soft Delete on all buckets in the project\r\n$ gcloud storage buckets update --clear-soft-delete gs://*\r\n\r\n# Enable Soft Delete on one bucket\r\n$ gcloud storage buckets update --soft-delete-duration=7d gs://example-bucket\r\n\r\n# Enable Soft Delete on a list of buckets\r\n$ cat buckets.txt | gcloud storage buckets update -I --soft-delete-duration=7d\r\n\r\n# Enable Soft Delete on all buckets in the project with a 14-day retention duration\r\n$ gcloud storage buckets update --soft-delete-duration=14d gs://*'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc22f0340>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><h2><span style="vertical-align: baseline;">Taking action with Terraform</span></h2>
+<p><span style="vertical-align: baseline;">If you use an orchestration layer like </span><a href="https://cloud.google.com/docs/terraform"><span style="text-decoration: underline; vertical-align: baseline;">Terraform</span></a><span style="vertical-align: baseline;">, adapting to soft delete should be as simple as updating your templates and deciding on the soft delete retention duration for each workload. This could also involve creating new templates dedicated to short-lived data so that soft delete is disabled for buckets created from those templates. Once you’ve defined your settings, Terraform can update existing buckets to conform to the templates, and new buckets should be created with your intended settings.</span></p>
+<p><span style="vertical-align: baseline;">With Terraform, the primary thing you need to do is to update your template(s) to include a soft delete policy. Here is an example of setting the soft delete retention duration to seven days (604800 seconds) in a </span><code style="vertical-align: baseline;">google_storage_bucket</code><span style="vertical-align: baseline;"> resource:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'resource "google_storage_bucket" "bucket" {\r\n name = "example-bucket"\r\n location = "US"\r\n …\r\n soft_delete_policy {\r\n retention_duration_seconds = 604800\r\n }\r\n ...\r\n}'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc22f0160>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">To disable soft delete instead, simply set </span><code style="vertical-align: baseline;">retention_duration_seconds = 0</code><span style="vertical-align: baseline;">.</span></p>
+<p><span style="vertical-align: baseline;">For more information, please also see: </span><a href="https://cloud.google.com/storage/docs/terraform-create-bucket-upload-object"><span style="text-decoration: underline; vertical-align: baseline;">Use Terraform to create storage buckets and upload objects</span></a><span style="vertical-align: baseline;">.</span></p>
+<h2><span style="vertical-align: baseline;">Taking action across a large organization</span></h2>
+<p><span style="vertical-align: baseline;">If you work for a large enterprise with thousands of projects and millions of buckets and mostly don’t use an orchestration layer, then a manual approach is not realistic, and you will need to make decisions at scale. If this is your situation, we recommend that you first learn about the bucket-level metrics and how to take action within a project as described earlier. In this section, we’ll extend these techniques to the organization level. Again, we assume you have already installed an up-to-date version of the gcloud CLI which you will need for this section.</span></p>
+<p><span style="vertical-align: baseline;">To implement a policy across even the most complex of organizations, you will likely need to approach it in three steps using the gcloud command line environment:</span></p>
+<ol>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Obtain permissions: ensure you can list and change bucket-level settings across the organization</span></p>
+</li>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Assess: decide on an impact threshold above which you will disable soft delete, and obtain a list of buckets surpassing that threshold</span></p>
+</li>
+<li aria-level="1" style="list-style-type: decimal; vertical-align: baseline;">
+<p role="presentation"><span style="vertical-align: baseline;">Act: disable soft delete on that list of buckets</span></p>
+</li>
+</ol>
+<h3><span style="vertical-align: baseline;">Obtain permissions</span></h3>
+<p><span style="vertical-align: baseline;">Before you can do anything, you will need to identify someone with sufficient access permissions to analyze and change bucket-level configurations across your organization. This could be an existing </span><a href="https://cloud.google.com/resource-manager/docs/creating-managing-organization"><span style="text-decoration: underline; vertical-align: baseline;">Organization Administrator</span></a><span style="vertical-align: baseline;">. Alternatively, your Organization Administrator could create a custom role and assign it to you or another administrator for the specific purpose of managing soft delete settings:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'gcloud iam roles create storageBucketsUpdate \\\r\n --organization=example-organization-id-1 \\\r\n --title="Storage bucket update" \\\r\n --description="Grants permission to get, list, and update Storage buckets." \\\r\n --stage=GA \\\r\n --permissions="storage.buckets.get,storage.buckets.list,storage.buckets.update"\r\n\r\ngcloud organization add-iam-policy-binding example-organization-id-1 \\\r\n --member=\'user:test-user@example.com\' \\\r\n --role=\'storageBucketsUpdate\' \\\r\n --condition=\'expression=request.time < timestamp("2024-07-01T00:00:00Z"),\\\r\n title=expires_2024_07_01,\\\r\n description=Expires at midnight on 2024-07-01\''), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc22f0b20>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Note that once everything is done, at the end of this process, and your buckets are all updated, the Organization Administrator could safely delete this custom role if there wasn’t an ongoing need for a role with continued access to these settings:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'gcloud iam roles delete storageBucketsUpdate --organization=example-organization-id-1'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc22f0400>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><h3><span style="vertical-align: baseline;">Assess</span></h3>
+<p><span style="vertical-align: baseline;">Armed with the power to act on bucket-level configurations across your organization, you can apply the project-level analysis above to obtain a list of all buckets across your organization that exceed your chosen impact threshold. Alternatively, you might choose to apply a uniform setting like 0d or 14d across all buckets in your organization.</span></p>
+<h3><span style="vertical-align: baseline;">Act</span></h3>
+<p><span style="vertical-align: baseline;">To update the soft delete policy for all your buckets across all your projects, you can iterate through all your projects, making the appropriate changes to the buckets in each project. For example, the following command disables soft delete on all buckets across your organization:</span></p></div>
+<div class="block-code"><dl>
+ <dt>code_block</dt>
+ <dd><ListValue: [StructValue([('code', 'gcloud projects list --format="value(projectId)" | while read project\r\ndo\r\n gcloud storage buckets update --project=$project --clear-soft-delete gs://*\r\ndone'), ('language', ''), ('caption', <wagtail.rich_text.RichText object at 0x3eefc8d9cc10>)])]></dd>
+</dl></div>
+<div class="block-paragraph_advanced"><p><span style="vertical-align: baseline;">Alternatively, you can use the </span><code style="vertical-align: baseline;">filter</code><span style="vertical-align: baseline;"> option of </span><code style="vertical-align: baseline;">projects list</code><span style="vertical-align: baseline;"> to only target a subset of your projects. For example, you might want to update projects with a specific label (</span><code style="vertical-align: baseline;">--filter="labels.environment:prod"</code><span style="vertical-align: baseline;">) or with a certain parent (</span><code style="vertical-align: baseline;">--filter="parent.id:123456789"</code><span style="vertical-align: baseline;">).</span></p>
+<p><span style="vertical-align: baseline;">As a best practice, we recommend that you consider replacing the per-project action above with a command that selectively disables soft delete on specific bucket IDs. For example, you could loop through your project list, running the </span><a href="https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/storage/cost-analysis" rel="noopener" target="_blank"><span style="text-decoration: underline; vertical-align: baseline;">soft delete billing impact Python script</span></a><span style="vertical-align: baseline;"> for each project to update your bucket settings according to a % impact threshold you select to get a much more tailored outcome.</span></p>
+<h2><span style="vertical-align: baseline;">Summary</span></h2>
+<p><span style="vertical-align: baseline;">By following the best practices in this blog and taking advantage of the available tooling and controls, we hope that you now feel more confident in your ability to protect your business-critical data with soft delete while simultaneously minimizing its billing impact.</span></p></div>Wed, 01 May 2024 16:00:00 +0000https://cloud.google.com/blog/products/storage-data-transfer/understanding-cloud-storages-new-soft-delete-feature/Google Cloud NextStorage & Data TransferarticleManaging Cloud Storage soft delete at scalehttps://storage.googleapis.com/gweb-cloudblog-publish/images/optimization_2022.max-600x600.jpgGooglehttps://cloud.google.com/blog/products/storage-data-transfer/understanding-cloud-storages-new-soft-delete-feature/Geoffrey NoerGroup Product ManagerMichael RothSoftware Engineer
\ No newline at end of file
diff --git a/exper/raw/yicai.brief.xml b/exper/raw/yicai.brief.xml
index 3f5e6f4..bb5be32 100644
--- a/exper/raw/yicai.brief.xml
+++ b/exper/raw/yicai.brief.xml
@@ -1,822 +1,2557 @@
-
-CNCF - Bloghttps://www.cncf.io/blog/CNCF - Blog - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)RSSHubi@diygod.me (DIYgod)enWed, 08 May 2024 05:32:55 GMT1Kubernetes is turning 10! Join the party on June 6th<p>Over the last 10 years, <a href="http://kubernetes.io/">Kubernetes</a> has risen to become the backbone of modern application deployment and has completely changed the course of innovation. </p>
->
-
-
- https://www.yicai.com/brief
-
-
- RSSHub
- i@diygod.me (DIYgod)
-
-
-
- zh-cn
-
- Sun, 07 Jan 2024 19:34:33 GMT
- 5
-
-
- 首钢集团:网传“违法开除员工”女高管非首钢员工 | 首钢集团有限公司就网传“北京首钢女高管违法开除员工”消息发布声明。声明表示,网传视频中的女子并...]]>
- 首钢集团:网传“违法开除员工”女高管非首钢员工 | 首钢集团有限公司就网传“北京首钢女高管违法开除员工”消息发布声明。声明表示,网传视频中的女子并非首钢集团员工或高管,有关事件与首钢集团没有任何关系。]]>
- Sun, 07 Jan 2024 15:51:00 GMT
- https://www.yicai.com/brief/101949358.html
- https://www.yicai.com/brief/101949358.html
-
-
-
-
-
-
-
-
-
-
-
- 日本石川县能登地区发生4.0级地震 | 据日本朝日电视台消息,当地时间7日23时44分左右,日本石川县能登地区发生4.0级地震,最大震感为震度3,震源深度10公...]]>
- 日本石川县能登地区发生4.0级地震 | 据日本朝日电视台消息,当地时间7日23时44分左右,日本石川县能登地区发生4.0级地震,最大震感为震度3,震源深度10公里。(央视新闻)]]>
- Sun, 07 Jan 2024 15:09:00 GMT
- https://www.yicai.com/brief/101949356.html
- https://www.yicai.com/brief/101949356.html
-
-
-
-
-
-
-
-
-
-
-
- 日本外相与乌克兰总统举行会谈 | 当地时间7日,据日本时事通讯社消息,正在乌克兰访问的日本外相上川阳子与乌克兰总统泽连斯基举行了会谈。(央视新闻)]]>
- 日本外相与乌克兰总统举行会谈 | 当地时间7日,据日本时事通讯社消息,正在乌克兰访问的日本外相上川阳子与乌克兰总统泽连斯基举行了会谈。(央视新闻)]]>
- Sun, 07 Jan 2024 14:52:00 GMT
- https://www.yicai.com/brief/101949354.html
- https://www.yicai.com/brief/101949354.html
-
-
-
-
-
-
-
-
-
-
-
- 以军持续轰炸加沙地带南部汗尤尼斯,已致71人死亡 | 据巴勒斯坦通讯社当地时间1月7日下午报道称,自6日夜间以来,以军对加沙地带南部汗尤尼斯地区持续空...]]>
- 以军持续轰炸加沙地带南部汗尤尼斯,已致71人死亡 | 据巴勒斯坦通讯社当地时间1月7日下午报道称,自6日夜间以来,以军对加沙地带南部汗尤尼斯地区持续空袭和炮击,已造成71人死亡。(央视新闻)]]>
- Sun, 07 Jan 2024 14:40:00 GMT
- https://www.yicai.com/brief/101949352.html
- https://www.yicai.com/brief/101949352.html
-
-
-
-
-
-
-
-
-
-
-
- 平均船龄创新高,全球航运船队船舶出现老化趋势 | 英国金融时报7日报道,船舶经纪公司克拉克森的数据显示,2023年12月份,全球航运船队的平均船龄达到13....]]>
- 平均船龄创新高,全球航运船队船舶出现老化趋势 | 英国金融时报7日报道,船舶经纪公司克拉克森的数据显示,2023年12月份,全球航运船队的平均船龄达到13.7年,为2009年以来的最高水平;集装箱运输船队的船龄达到14.3年,这是自1993年该公司开始收集此项数据以来的最高值;而运载石油和其他液体的油轮平均船龄达12.9年,也创下20年来的新高。尽管全球脱碳压力在不断增加,但由于监管政策和新型替代燃料技术的不确定性,可能导致不少船东不愿订购采用环保燃料的新船。业内人士分析,船舶老化趋势或将持续。 (央视财经)]]>
- Sun, 07 Jan 2024 14:39:00 GMT
- https://www.yicai.com/brief/101949350.html
- https://www.yicai.com/brief/101949350.html
-
-
-
-
-
-
-
-
-
-
-
- 汤姆猫:公司目前在研AI应用仍在测试与打磨阶段 | 汤姆猫近日在电话会议上表示,公司目前在研的AI应用仍在测试与打磨阶段。其中:公司国内研发团队与西湖...]]>
- 汤姆猫:公司目前在研AI应用仍在测试与打磨阶段 | 汤姆猫近日在电话会议上表示,公司目前在研的AI应用仍在测试与打磨阶段。其中:公司国内研发团队与西湖心辰合作的多模态AI汤姆猫产品及汤姆猫AI讲故事,已初步完成主要功能的测试,公司正进一步丰富汤姆猫AI讲故事的产品内容,同时携手西湖心辰团队持续完善产品的多模态、长期记忆、情感感知等功能模块;公司海外团队研发的首款AI手游《Talking Ben AI》已在斯洛文尼亚、塞浦路斯、南非等地区开启首轮海外测试,在此次测试中,公司获取了充足的合规语料,后续公司将根据测试获取的语料持续丰富该产品的预设数据库,同时公司海外团队也将携手西湖心辰进一步探讨海外测试产品Talking Ben AI的个性化交互、模型能力的提升以及AI技术的更广泛应用。]]>
- Sun, 07 Jan 2024 14:33:00 GMT
- https://www.yicai.com/brief/101949348.html
- https://www.yicai.com/brief/101949348.html
-
-
-
-
-
-
-
-
-
-
-
- 明日A股机会早知道 | ①央行连续第14个月增持黄金储备,黄金股迎来右侧配置时机
丽人丽妆:股东丽仁拟减持不超0.99%公司股份]]>
- Sun, 07 Jan 2024 09:46:00 GMT
- https://www.yicai.com/brief/101949258.html
- https://www.yicai.com/brief/101949258.html
-
-
-
-
-
-
-
-
-
-
-
- 鼎龙科技:拟收购控股子公司少数股权 | 鼎龙科技公告,公司拟以自有资金2954.10万元收购控股子公司鼎利科技少数股东双利科技持有的40%股权。收购完成后,...]]>
- 鼎龙科技:拟收购控股子公司少数股权 | 鼎龙科技公告,公司拟以自有资金2954.10万元收购控股子公司鼎利科技少数股东双利科技持有的40%股权。收购完成后,鼎利科技将成为公司全资子公司。]]>
- Sun, 07 Jan 2024 09:36:00 GMT
- https://www.yicai.com/brief/101949251.html
- https://www.yicai.com/brief/101949251.html
-
-
-
-
-
-
-
-
-
-
-
- 中信建投:2024年继续看好医疗器械板块投资机会,关注三条主线 | 中信建投证券研报认为,展望2024年,我们继续看好医疗器械板块的投资机会,看好政策拐点...]]>
- 中信建投:2024年继续看好医疗器械板块投资机会,关注三条主线 | 中信建投证券研报认为,展望2024年,我们继续看好医疗器械板块的投资机会,看好政策拐点、国际化和创新驱动三条主线。建议关注2024年有望受益于手术量复苏、招投标需求恢复的部分公司,海外业务高增长确定性强或有望超预期的公司,以及新产品、新技术放量催化下可能业绩增速提升的部分公司。预计2024年行业采购仍在温和复苏中,上半年部分高值耗材企业的业绩确定性高于IVD,高于医疗设备企业。]]>
- Sun, 07 Jan 2024 09:31:00 GMT
- https://www.yicai.com/brief/101949248.html
- https://www.yicai.com/brief/101949248.html
-
-
-
-
-
-
-
-
-
-
-
- 潮州市交通运输局原党组书记、局长佘延民被“双开” | 据南粤清风网消息,日前,经潮州市委批准,潮州市纪委监委对潮州市交通运输局原党组书记、局长佘延...]]>
- 潮州市交通运输局原党组书记、局长佘延民被“双开” | 据南粤清风网消息,日前,经潮州市委批准,潮州市纪委监委对潮州市交通运输局原党组书记、局长佘延民严重违纪违法问题进行了立案审查调查。依据《中国共产党纪律处分条例》《中华人民共和国监察法》《中华人民共和国公职人员政务处分法》等有关规定,经潮州市纪委常委会会议、市委常委会会议研究,并经广东省纪委常委会会议审议后报省委批准,决定给予佘延民开除党籍处分;由潮州市监委给予其开除公职处分;终止其潮州市第十五次党代会代表资格;收缴其违纪违法所得;将其涉嫌犯罪问题移送检察机关依法审查起诉,所涉财物一并移送。]]>
- Sun, 07 Jan 2024 09:18:00 GMT
- https://www.yicai.com/brief/101949246.html
- https://www.yicai.com/brief/101949246.html
-
-
-
-
-
-
-
-
-
-
-
- 东莞发放暖工稳产“大礼包”:每家企业最高可获30万元招用工补贴 | 广东东莞近日印发实施《关于春节前后暖工稳产促消费的若干措施》,从稳工稳岗促就业、...]]>
- 东莞发放暖工稳产“大礼包”:每家企业最高可获30万元招用工补贴 | 广东东莞近日印发实施《关于春节前后暖工稳产促消费的若干措施》,从稳工稳岗促就业、稳产促增抢先机、丰富供给促消费三大方面使用政策工具包。2024年2月10日至3月9日期间,企业招用初次在东莞就业的非东莞户籍人员,签订劳动合同并依法连续参加社保满3个月以上,按1000元/人标准给予企业一次性新增就业补贴,每家企业最高30万元。(新华社)]]>
- Sun, 07 Jan 2024 09:12:00 GMT
- https://www.yicai.com/brief/101949244.html
- https://www.yicai.com/brief/101949244.html
-
-
-
-
-
-
-
-
-
-
-
- 日本能登半岛地震导致部分海域变成陆地 | 日本媒体6日援引研究人员的话报道,日本石川县能登半岛地震导致沿海部分海底抬升变成陆地。据《读卖新闻》报道...]]>
- 日本能登半岛地震导致部分海域变成陆地 | 日本媒体6日援引研究人员的话报道,日本石川县能登半岛地震导致沿海部分海底抬升变成陆地。据《读卖新闻》报道,日本国土地理院研究人员分析卫星观测数据,发现从能登半岛珠洲市经轮岛市至志贺町的沿岸海底隆起露出水面,总长度大约85公里。其中,轮岛市皆月湾一带海底隆起大约4米,海岸线向海中推进大约200米。日本地理学会研究人员分析航空摄影图片,发现仅在珠洲市至轮岛市沿岸大约50公里范围内,陆地面积就扩大约240公顷。(新华社)]]>
- Sun, 07 Jan 2024 09:09:00 GMT
- https://www.yicai.com/brief/101949242.html
- https://www.yicai.com/brief/101949242.html
-
-
-
-
-
-
-
-
-
-
-
- 奥飞娱乐:后续将会推出《巴啦啦小魔仙10》等新作品 | 奥飞娱乐在互动平台表示,《星缘蝶启1》和《星缘蝶启2》分别为《巴啦啦小魔仙9》的第一季和第二季...]]>
- 奥飞娱乐:后续将会推出《巴啦啦小魔仙10》等新作品 | 奥飞娱乐在互动平台表示,《星缘蝶启1》和《星缘蝶启2》分别为《巴啦啦小魔仙9》的第一季和第二季内容,目前没有制作第三季内容的规划,公司后续将会推出《巴啦啦小魔仙10》等新作品。]]>
- Sun, 07 Jan 2024 09:04:00 GMT
- https://www.yicai.com/brief/101949240.html
- https://www.yicai.com/brief/101949240.html
-
-
-
-
-
-
-
-
-
-
-
- 日本石川县轮岛市发出避难指示,当地或将发生大规模山体滑坡 | 当地时间1月7日,日本石川县轮岛市市长坂口茂在当天举行的石川县灾害对策本部会议中称,轮...]]>
- 日本石川县轮岛市发出避难指示,当地或将发生大规模山体滑坡 | 当地时间1月7日,日本石川县轮岛市市长坂口茂在当天举行的石川县灾害对策本部会议中称,轮岛市可能发生大规模山体滑坡的迹象,为此已向当地居民发出避难指示。(新华社)]]>
- Sun, 07 Jan 2024 09:02:00 GMT
- https://www.yicai.com/brief/101949238.html
- https://www.yicai.com/brief/101949238.html
-
-
-
-
-
-
-
-
-
-
-
- 昔日深圳珠宝第一股拉响退市警报 | 自2023年12月22日起,截至2024年1月5日,*ST爱迪已连续10个交易日收盘价低于1元。根据交易所相关规定,若公司股票连续...]]>
- 昔日深圳珠宝第一股拉响退市警报 | 自2023年12月22日起,截至2024年1月5日,*ST爱迪已连续10个交易日收盘价低于1元。根据交易所相关规定,若公司股票连续20个交易日的股票收盘价均低于1元,将会触及交易类强制退市的情形。值得注意的是,*ST爱迪最新收盘价为0.62元,在接下来的10个交易日中,*ST爱迪需连续涨停才有希望在第20个交易日重返1元,短暂规避交易类强制退市类型。2015年,公司顶着深圳珠宝第一股的光环上市。上市之后,公司曾多次进行资本运作。(中国基金报)]]>
- Sun, 07 Jan 2024 09:00:00 GMT
- https://www.yicai.com/brief/101949236.html
- https://www.yicai.com/brief/101949236.html
-
-
-
-
-
-
-
-
-
-
-
- 佐力药业:获得百令胶囊药品注册证书 | 佐力药业公告,近日,公司收到国家药监局签发的百令胶囊《药品注册证书》。百令胶囊功能主治:补肺肾、益精气。用...]]>
- 佐力药业:获得百令胶囊药品注册证书 | 佐力药业公告,近日,公司收到国家药监局签发的百令胶囊《药品注册证书》。百令胶囊功能主治:补肺肾、益精气。用于肺肾两虚引起的咳嗽、气喘、咯血、腰背酸痛、面目虚浮、夜尿清长;慢性支气管炎、慢性肾功能不全的辅助治疗。]]>
- Sun, 07 Jan 2024 08:39:00 GMT
- https://www.yicai.com/brief/101949234.html
- https://www.yicai.com/brief/101949234.html
-
-
-
-
-
-
-
-
-
-
-
- 独家|汽车后市场生变:集群车宝申请破产 已有加盟店改换门头 | 原国美华南大区总经理高集群创办的集群车宝1月3日起申请破产,随着新能源车普及、京东等...]]>
- 独家|汽车后市场生变:集群车宝申请破产 已有加盟店改换门头 | 原国美华南大区总经理高集群创办的集群车宝1月3日起申请破产,随着新能源车普及、京东等巨头切入,加上经济环境影响,汽车后市场生变,令中小型的服务商生存变难。第一财经记者1月7日在集群车宝广州市海珠区怡安路店看到,这家集群车宝的加盟店门头已经更名。该店相关负责人说,已向顾客售出的集群车宝业务,门店会继续提供服务。除了外部原因外,集群车宝的破产也跟自身在汽车后市场业务的数字化转型不顺有关。(第一财经记者 王珍)]]>
- Sun, 07 Jan 2024 08:39:00 GMT
- https://www.yicai.com/brief/101949232.html
- https://www.yicai.com/brief/101949232.html
-
-
-
-
-
-
-
-
-
-
-
- 美年健康:拟与美因健康签署基因检测项目合作协议 | 美年健康公告,公司拟与美因健康科技(北京)有限公司(简称“美因健康”)签署《基因检测项目合作协...]]>
- 美年健康:拟与美因健康签署基因检测项目合作协议 | 美年健康公告,公司拟与美因健康科技(北京)有限公司(简称“美因健康”)签署《基因检测项目合作协议》,向公司及下属子公司客户销售美因健康的基因检测产品,美因健康按公司及下属子公司提出的项目产品要求为公司及下属子公司客户提供基因检测服务。美因健康为香港主板上市公司Mega Genomics Limited(HK.06667,简称“美因基因”)通过协议控制的境内运营实体。预计2024年度本协议项下双方交易金额不超过1.5亿元,合作协议的有效期为三年。]]>
- Sun, 07 Jan 2024 08:31:00 GMT
- https://www.yicai.com/brief/101949230.html
- https://www.yicai.com/brief/101949230.html
-
-
-
-
-
-
-
-
-
-
-
- 以军空袭加沙北部造成至少20人死亡 | 据巴勒斯坦通讯社7日报道,以色列军队6日夜间空袭加沙地带北部杰巴利耶难民营一处住宅,造成至少20人死亡。(新华社...]]>
- 以军空袭加沙北部造成至少20人死亡 | 据巴勒斯坦通讯社7日报道,以色列军队6日夜间空袭加沙地带北部杰巴利耶难民营一处住宅,造成至少20人死亡。(新华社)]]>
- Sun, 07 Jan 2024 08:30:00 GMT
- https://www.yicai.com/brief/101949228.html
- https://www.yicai.com/brief/101949228.html
-
-
-
-
-
-
-
-
-
-
-
- 金新农:2023年累计生猪销售收入12.38亿元 同比减少31.95% | 金新农公告,公司2023年12月生猪销量9.93万头(其中商品猪7.41万头、仔猪2.15万头、种猪0.37...]]>
- 金新农:2023年累计生猪销售收入12.38亿元 同比减少31.95% | 金新农公告,公司2023年12月生猪销量9.93万头(其中商品猪7.41万头、仔猪2.15万头、种猪0.37万头),销售收入1.26亿元,商品猪销售均价13.38元/公斤,环比下降8.33%。2023年1-12月,公司累计销售生猪104.69万头,同比减少16.67%;累计生猪销售收入12.38亿元,同比减少31.95%。]]>
- Sun, 07 Jan 2024 08:23:00 GMT
- https://www.yicai.com/brief/101949224.html
- https://www.yicai.com/brief/101949224.html
-
-
-
-
-
-
-
-
-
-
-
- 韩国联合参谋本部:朝鲜7日继续进行海岸炮射击 | 据韩国联合参谋本部当地时间1月7日报道,朝鲜军队7日继续在延坪岛北方进行了海岸炮射击。朝鲜方面对此暂...]]>
- 韩国联合参谋本部:朝鲜7日继续进行海岸炮射击 | 据韩国联合参谋本部当地时间1月7日报道,朝鲜军队7日继续在延坪岛北方进行了海岸炮射击。朝鲜方面对此暂无回应。 (央视新闻)]]>
- Sun, 07 Jan 2024 08:21:00 GMT
- https://www.yicai.com/brief/101949222.html
- https://www.yicai.com/brief/101949222.html
-
-
-
-
-
-
-
-
-
-
-
- 福田汽车:2023年汽车产品累计销量同比增长37.14% | 福田汽车晚间公告,2023年12月份汽车产品合计销量64809辆,其中新能源汽车4063辆;1—12月汽车产品累...]]>
- 福田汽车:2023年汽车产品累计销量同比增长37.14% | 福田汽车晚间公告,2023年12月份汽车产品合计销量64809辆,其中新能源汽车4063辆;1—12月汽车产品累计销量63.1万辆,同比增长37.14%。]]>
- Sun, 07 Jan 2024 08:03:00 GMT
- https://www.yicai.com/brief/101949220.html
- https://www.yicai.com/brief/101949220.html
-
-
-
-
-
-
-
-
-
-
-
- 丽人丽妆:股东丽仁拟减持不超0.99%公司股份 | 丽人丽妆晚间公告,股东丽仁拟通过大宗交易和/或集中竞价方式合计减持公司股份数量不超过397.98万股,占公...]]>
- 丽人丽妆:股东丽仁拟减持不超0.99%公司股份 | 丽人丽妆晚间公告,股东丽仁拟通过大宗交易和/或集中竞价方式合计减持公司股份数量不超过397.98万股,占公司总股本的0.99%。]]>
- Sun, 07 Jan 2024 08:02:00 GMT
- https://www.yicai.com/brief/101949218.html
- https://www.yicai.com/brief/101949218.html
-
-
-
-
-
-
-
-
-
-
-
- 恒瑞医药:公司及子公司获得药品注册证书 | 恒瑞医药公告,公司近日收到国家药监局核准签发的盐酸伊立替康脂质体注射液(Ⅱ)《药品注册证书》;子公司山东...]]>
- 恒瑞医药:公司及子公司获得药品注册证书 | 恒瑞医药公告,公司近日收到国家药监局核准签发的盐酸伊立替康脂质体注射液(Ⅱ)《药品注册证书》;子公司山东盛迪医药有限公司收到国家药监局核准签发的恒格列净二甲双胍缓释片(Ⅰ)、(Ⅱ)《药品注册证书》。]]>
- Sun, 07 Jan 2024 08:02:00 GMT
- https://www.yicai.com/brief/101949216.html
- https://www.yicai.com/brief/101949216.html
-
-
-
-
-
-
-
-
-
-
-
- 中信证券:场外配置型资金预计将逐步入场,市场将迎来重要拐点 | 中信证券发布研报表示,开年首周资金的跨年效应显著,机构调仓和加仓均抱团于红利低波,...]]>
- 中信证券:场外配置型资金预计将逐步入场,市场将迎来重要拐点 | 中信证券发布研报表示,开年首周资金的跨年效应显著,机构调仓和加仓均抱团于红利低波,市场交易生态和风格分化趋于极致;1月中旬是关键时点,随着经济数据和地缘扰动的落地,政策将持续加码,场外配置型资金预计将逐步入场,市场将迎来重要拐点,当前依然建议优先布局以科创为代表的超跌成长。]]>
- Sun, 07 Jan 2024 08:01:00 GMT
- https://www.yicai.com/brief/101949214.html
- https://www.yicai.com/brief/101949214.html
-
-
-
-
-
-
-
-
-
-
-
-
+
+<p>Kubernetes was the first project <a href="https://www.cncf.io/announcements/2016/03/10/cloud-native-computing-foundation-accepts-kubernetes-as-first-hosted-project-technical-oversight-committee-elected/">accepted</a> into the CNCF Incubator in March 2016 and remains a top open source project. Kubernetes not only shattered expectations for itself but it set a North Star for the entire CNCF ecosystem. CNCF has since grown to more than 184 cloud native projects and the success of Kubernetes in the CNCF established a baseline of what was possible for others. </p>
+
+
+
+<p>Kubernetes is today the de facto standard to deploy and operate containerized applications. Originally developed at Google and released as open source in 2014, Kubernetes builds on 15 years of running Google’s containerized workloads and the valuable contributions from the open source community. Kubernetes makes everything associated with deploying and managing applications easier.</p>
+
+
+
+<p><a href="https://events.linuxfoundation.org/kuber10es-birthday-bash/">On June 6</a>, the Kubernetes and cloud native community will come together across the globe to celebrate a tremendous decade and look forward to the next #KuberTENes. Everyone in the community will have a chance to #celebr8k8s in the following ways.</p>
+
+
+
+<h2 class="wp-block-heading"><strong>KuberTENes Birthday Bash</strong></h2>
+
+
+
+<p>Join us for a fun and memorable in-person event at Google’s <a href="https://realestate.withgoogle.com/bayview">Bay View Campus</a> in Mountain View, California to celebrate on June 6th.</p>
+
+
+
+<p>The birthday bash will blend elements of a reunion show, while celebrating many hidden figures that made this project possible, and a preview into what awaits us in the next 10 years. We’ll celebrate people who have been integral in shaping Kubernetes into what it is today, and discuss why its significance will only grow in the years ahead. </p>
+
+
+
+<p>Interested in attending? We would love to have you. Tickets are free but space is limited so <a href="https://events.linuxfoundation.org/kuber10es-birthday-bash/">RSVP</a> soon! </p>
+
+
+
+<h3 class="wp-block-heading"><strong>Birthday Bash Livestream/Replays</strong></h3>
+
+
+
+<p>Can’t join the party in Mountain View? No problem! We will have a livestream during the event and the recording will be available as well on YouTube for all to see. </p>
+
+
+
+<h2 class="wp-block-heading"><strong>KuberTENes Birthday Party in a Box & Local Meet-Ups</strong></h2>
+
+
+
+<p>If you’re unable to attend in the Bay Area or simply can’t make it, don’t fret! You can still join the celebration in your local community. Request a <a href="https://share.hsforms.com/1feeTKzUpRqm5lnnifbqOXQ4tvhy?__hstc=160532258.e00e885cf17bfdbb3d74d6b37932e9de.1698502436143.1713989333711.1714401664068.20&__hssc=160532258.1.1714401664068&__hsfp=1717932986">KuberTENes party in box here</a>, please note all requests need to be made by May 10. Alternatively, you can connect with local <a href="http://community.cncf.io/">Cloud Native Meet-Up Groups</a>, who are already working hard to organize events in your area. Some of the locations on the list (but not limited to) include:</p>
+
+
+
+<ul>
+<li>Cloud Native Wellington</li>
+
+
+
+<li>Cloud Native Quebec</li>
+
+
+
+<li>Cloud Native Luxembourg</li>
+
+
+
+<li>Cloud Native Helsink</li>
+
+
+
+<li>Cloud Native Dahaka</li>
+
+
+
+<li>Cloud Native Chattogram</li>
+
+
+
+<li>Cloud Native Paris</li>
+
+
+
+<li>Cloud Native Tel Aviv</li>
+
+
+
+<li>Cloud Native Singapore</li>
+
+
+
+<li>Cloud Native Taiwan User Group</li>
+
+
+
+<li>Cloud Native Copenhagen</li>
+
+
+
+<li>Cloud Native Aarhus</li>
+
+
+
+<li>Cloud Native Santa Catarina</li>
+
+
+
+<li>Cloud Native New York Kubernetes Meetup</li>
+
+
+
+<li>CloudNative Lorient</li>
+
+
+
+<li>Cloud Native Saint Louis</li>
+
+
+
+<li>Cloud Native Guatemala</li>
+
+
+
+<li>Cloud Native Vilnius</li>
+
+
+
+<li>Cloud Native Istanbul</li>
+
+
+
+<li>Cloud Native Kerala</li>
+
+
+
+<li>Cloud Native New Delhi</li>
+
+
+
+<li>Cloud Native Stockholm</li>
+
+
+
+<li>Cloud Native Aalborg</li>
+
+
+
+<li>Cloud Native Goteborg</li>
+
+
+
+<li>Cloud Native Amsterdam</li>
+
+
+
+<li>Cloud Native and Kubernetes Oslo</li>
+
+
+
+<li>Cloud Native Dallas</li>
+
+
+
+<li>Cloud Native Sao Paulo </li>
+
+
+
+<li>Cloud Native Munich</li>
+
+
+
+<li>Cloud Native Bangalore</li>
+
+
+
+<li>Cloud Native Salt Lake City</li>
+</ul>
+
+
+
+<p>And, whether you join one of these events, be sure to join the biggest gathering of Kubernetes enthusiasts in Salt Lake City for<a href="https://events.linuxfoundation.org/kubecon-cloudnativecon-north-america/"> KubeCon + CloudNativeCon North America</a> where we plan to continue the 10-year celebrations.</p>
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+
+
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+https://www.cncf.io/blog/2024/05/07/kubernetes-is-turning-10-join-the-party-on-june-6th/https://www.cncf.io/blog/2024/05/07/kubernetes-is-turning-10-join-the-party-on-june-6th/Mon, 06 May 2024 16:00:00 GMTAdding color-blind themes to Kubecolor to make Kubernetes more inclusive<p><em>Ambassador post originally published on <a href="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/">Sebastian “Prune” Thomas’s blog</a></em></p>
+
+
+
+<figure class="wp-block-image"><img decoding="async" src="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/images/kubecolor-logo-impaired.png" alt="image" referrerpolicy="no-referrer"></figure>
+
+
+
+<p><a href="https://github.com/kubecolor/kubecolor">Kubcolor</a> is a thin wrapper over the <code>kubectl</code> command that adds coloring to the output.</p>
+
+
+
+<p>I cloned the project and started maintaining it back in 2022 when the original author wasn’t active anymore.</p>
+
+
+
+<figure class="wp-block-image"><img decoding="async" src="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/images/Kubecolor_Logo_White.png" alt="KubeColor" referrerpolicy="no-referrer"></figure>
+
+
+
+<p>KubeColor can reformats the output of most <code>kubectl</code> commands to add colors and clarity. It makes it <em>so easier</em> to read the output that I still don’t understand that it’s not more widely used. I actually <a href="https://www.youtube.com/live/PWZJzjB7vso?si=CvfnmmdSZP3txENZ&t=32723">gave a lightning talk about it at the KubeCon’s Cloud Native Reject Europe 2024 in Paris</a> if you want a video pitch.</p>
+
+
+
+<p>One of the longest requested feature, discussed at length in the previous project, was to be able to cusotmize the color theme used by KubeColor.</p>
+
+
+
+<p>Actually, when I first cloned the original project, I applied a patch that was globally changing the colors to make thinks less colory and more standard, limiting to a smaller set of colors. Some people started complaining right away, but that’s what people do anyways.</p>
+
+
+
+<p>As of <strong>version 0.3.0</strong>, <code>kubecolor</code> now supports custom color scheme and theme, thanks to the work of other main contributor, <a href="https://github.com/applejag">AppleJag</a>, which is a talented (Go) devleoper. Jag, I can’t thank you enough for all the help on this project.</p>
+
+
+
+<figure class="wp-block-image"><img decoding="async" src="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/images/1.png" alt="image" referrerpolicy="no-referrer"></figure>
+
+
+
+<h2 class="wp-block-heading"><strong>What’s the problem ?</strong></h2>
+
+
+
+<p>By default <code>kubecolor</code> uses the set of colors from your terminal’s config, so it always was possible to configure it. Just change the theme of your terminal and you can adapt the colors to your needs !</p>
+
+
+
+<p>But more than colors default colors, some want to colorize some specific fields differently, or use more colors to further differenciate things.</p>
+
+
+
+<h2 class="wp-block-heading"><strong>But there’s more…</strong></h2>
+
+
+
+<p>According to <a href="https://enchroma.com/blogs/beyond-color/interesting-facts-about-color-blindness">this article</a>, one man out of 12 have some sort of <strong>color blindness</strong> (or color disability). Women are a little less concerned, with one out of 200, but still, it’s a lot ! (numbers may vary depending on the website too…)</p>
+
+
+
+<p>Check the <a href="https://en.wikipedia.org/wiki/Color_blindness">Wikipedia</a> page to learn more, and there’s tons of other sites about this matter. And still, it’s usually not something we think of right away.</p>
+
+
+
+<p>For example, just look at <a href="https://piratemakers.ca/posts/">my blog</a>, with it’s low contrast grey colors and you’ll understand that color blindness was not my main concerns at the time.</p>
+
+
+
+<p>And, well, when we think at inclusion it’s generally genders and skin colors, and when we think about accessibility, it’s mobility impairement, deafs and blinds.</p>
+
+
+
+<p><strong>Color-blindness</strong> is usually not mentionned or taken care of. The <a href="https://contribute.cncf.io/accessibility/">CNCF Website itself</a> does not mention it directly. The only TAG (Technical Advisory Groups) in the <code>Accessibility</code> section is <a href="https://contribute.cncf.io/accessibility/deaf-and-hard-of-hearing/">focused on hearing issues</a>.</p>
+
+
+
+<p>Maybe because it’s easier to live with color-blindness, or because people don’t talk about it by shame, it’s still a real problem and the numbers are huge, far more that what I always belived.</p>
+
+
+
+<p>Note that I’m not trying to rate any of those against the others, or trying to speak in place of the impacted persons. I’m not impaired and I just want to put some light on inclusivity.</p>
+
+
+
+<h2 class="wp-block-heading" id="so-what-to-do-with-this-">So, what to do with this ?</h2>
+
+
+
+<p>As soon as <code>kubecolor</code> got the color theme functionnality, I started thinking of adding one or multiple color themes for the various kind of color-blindness.</p>
+
+
+
+<p>The first question that came to my mind was :</p>
+
+
+
+<blockquote class="wp-block-quote is-style-smaller-quote is-layout-flow wp-block-quote-is-layout-flow">
+<p>It’s quite usual to use <code>green </code>for good things (success) and <code>red </code>for bad things (errors). But is there a common pattern for color-blind persons ?</p>
+</blockquote>
+
+
+
+<p>Well, so far I don’t have the answer. But while searching I learnt few things:</p>
+
+
+
+<ul>
+<li>Color is important, but so is the <code>contrast</code></li>
+
+
+
+<li>there’s also modifiers like <strong>bold</strong> and <em>italic</em> that can help better differenciate things</li>
+
+
+
+<li>it is usually better to add some text explaining the status and not only rely on the color. Here, no probleme for us, as we are <em>adding</em> colors to an already expressive text.</li>
+
+
+
+<li>Maybe I should not add a theme at all and each person will built its own</li>
+</ul>
+
+
+
+<h2 class="wp-block-heading" id="understanding-kubecolor-themes">Understanding KubeColor Themes</h2>
+
+
+
+<p>Thanks to Jag, <code>kubecolor</code> can process <a href="https://github.com/kubecolor/kubecolor/blob/main/README.md#color-theme">many kind of definitions to configure the colors</a>.</p>
+
+
+
+<p>In short:</p>
+
+
+
+<ul>
+<li>using a regular <strong>color names</strong> (like red, blue) will use whatever is defined in your <code>terminal</code> application’s theme. <code>white</code> may be white, or not, but <em>if</em> you already have a theme made for color-blindness, you may not have to change anything.</li>
+
+
+
+<li>using many other ways to define colors, like HEX and RGB values, will allow to use custom colors not part of your terminal’s theme.</li>
+
+
+
+<li>using <code>bg=</code> or <code>fg=</code> will allow to change the background or the front (text) color.</li>
+
+
+
+<li>it is possible to use any of the <code>modifiers</code> like <strong>bold</strong>, <em>italic</em> and so on to even better tune the visibility of each field.</li>
+
+
+
+<li>thanks to all the <code>KUBECOLOR_THEME_*</code> ENV variables, it is possible to fully customize the output of “each” field, depending on the original command used against <code>kubectl</code> (like <code>get</code> or a <code>describe</code>).</li>
+
+
+
+<li>it is possible to create the theme as a file, which also enable sharing it, by creating a <code>~/.kube/color.yaml</code> file (in OsX and Linux, may be a different location on Windows). We’ll dive on the format later, keep reading.</li>
+
+
+
+<li><code>kubecolor</code> embeds default themes, both in dark and light mode:
+<ul>
+<li>dark<img decoding="async" src="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/images/dark-theme.png" alt="image" referrerpolicy="no-referrer"></li>
+
+
+
+<li>light</li>
+
+
+
+<li>pre-0.0.21-dark: the previous color schema from the original project<img decoding="async" src="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/images/pre-0.0.21-dark-theme.png" alt="image" referrerpolicy="no-referrer"></li>
+
+
+
+<li>pre-0.0.21-light</li>
+</ul>
+</li>
+</ul>
+
+
+
+<p>You can check the content of each basic theme in the code in the <a href="https://github.com/kubecolor/kubecolor/blob/main/config/theme.go#L15">config/theme.go</a> file.</p>
+
+
+
+<h2 class="wp-block-heading" id="how-to-build-a-theme">How to build a theme</h2>
+
+
+
+<p>As said earlier, you can either use the <code>KUBECOLOR_THEME_*</code> env variables or create your theme in the <code>~/.kube/color.yaml</code> file.</p>
+
+
+
+<h3 class="wp-block-heading" id="using-env-variables">Using ENV Variables</h3>
+
+
+
+<p>The easiest is to check the docs at <a href="https://github.com/kubecolor/kubecolor/blob/main/README.md#color-theme">https://github.com/kubecolor/kubecolor/blob/main/README.md#color-theme</a> and experiment.</p>
+
+
+
+<p>In any case, you have to pick a <code>base</code> theme, by setting <code>KUBECOLOR_PRESET</code>, then update some of the colors. For example you can change all the <code>running</code> pods to blue with:</p>
+
+
+
+<pre class="wp-block-code"><code class="">KUBECOLOR_THEME_BASE_SUCCESS=blue KUBECOLOR_PRESET=dark kubecolor get pods -o wide
+</code></pre>
+
+
+
+<p>Bash</p>
+
+
+
+<figure class="wp-block-image"><img decoding="async" src="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/images/running-blue.png" alt="image" referrerpolicy="no-referrer"></figure>
+
+
+
+<h3 class="wp-block-heading" id="using-the-config-file">Using the config file</h3>
+
+
+
+<p>Create the file <code>~/.kube/color.yaml</code> and add some content like:</p>
+
+
+
+<pre class="wp-block-code"><code class="">preset: dark
+theme:
+ table:
+ header: fg=red:bold:bg=blue
+</code></pre>
+
+
+
+<p>YAML</p>
+
+
+
+<p>So basically, you take the ENV variable and you nest the last part of it.</p>
+
+
+
+<p>With <code>KUBECOLOR_THEME_STATUS_ERROR</code>, you remove the <code>KUBECOLOR</code> part, so the final path is <code>theme.status.error</code>, so to show pods in error in pink:</p>
+
+
+
+<pre class="wp-block-code"><code class="">preset: dark
+theme:
+ table:
+ header: fg=red:bold:bg=blue
+ status:
+ error: pink
+</code></pre>
+
+
+
+<p>YAML</p>
+
+
+
+<figure class="wp-block-image"><img decoding="async" src="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/images/crash-magenta.png" alt="image" referrerpolicy="no-referrer"></figure>
+
+
+
+<h2 class="wp-block-heading" id="color-blind-theme">Color Blind Theme</h2>
+
+
+
+<p>First I want to clearly state I do not have any color impairement, and the work I’m trying to achieve here is based on articles I read and some talking with color-blind persons. There’s no scientific work on my side.</p>
+
+
+
+<p>The idea is to provide an out of the box solution to help people with color-blindness. The outcome may not be perfect or even useful and I take no responsability. It’s best effort. It’s OpenSource. Bare with me.</p>
+
+
+
+<p>After some researches, I found the <a href="https://asada.website/webCVS/index.html">Cromatic Vision Simulator website</a> which allows to load an image and, using a quad view, see what color-blind persons may see depending on the kind of disability.</p>
+
+
+
+<p>In short, if I upload one of the previous images that captured the <code>k get pods -o wide</code> commands, we can check how it look using the <code>dark</code> theme:</p>
+
+
+
+<ul>
+<li>regular view<img decoding="async" src="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/images/get-pods-dark.png" alt="image" referrerpolicy="no-referrer"></li>
+
+
+
+<li>Protanopia view<img decoding="async" src="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/images/get-pods-dark-protanopia.png" alt="image" referrerpolicy="no-referrer"></li>
+
+
+
+<li>deuteranopia view<img decoding="async" src="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/images/get-pods-dark-deuteranopia.png" alt="image" referrerpolicy="no-referrer"></li>
+
+
+
+<li>tritanopia view<img decoding="async" src="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/images/get-pods-dark-tritanopia.png" alt="image" referrerpolicy="no-referrer"></li>
+</ul>
+
+
+
+<p>Now I guess we all understand the issue with the current color scheme of the <code>dark</code> theme: any impaired person will lose most of the color informations. At this point, better use plain <code>kubectl</code> commands…</p>
+
+
+
+<p>So I tested some chromatic progressions to try to identify a palette that could work fine at least most of the time:</p>
+
+
+
+<figure class="wp-block-image"><img decoding="async" src="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/images/color-cycles-quad.png" alt="image" referrerpolicy="no-referrer"></figure>
+
+
+
+<p>Being color-blind is not just not seeing green or red, there’s also quite a limitation in the color hues that are perceived, so everything from green to red, where the color changes slowly for a regular eye, will be almost the same brown/yellowish for a Protanopian.</p>
+
+
+
+<p>My final conclusion is that it seems possible to achieve a theme that will help better differenciate the content. What we need here is having different color hues to show the difference of, mostly, good and bad situation, and color cycles when there’s a table.</p>
+
+
+
+<p>Using the <a href="https://observablehq.com/@d3/color-schemes">Observable HQ website</a>, I used the <code>discrete 10</code> schema to cut the rainbow in 10 usable colors:</p>
+
+
+
+<ul>
+<li><code>#23171b</code></li>
+
+
+
+<li><code>#4860e6</code></li>
+
+
+
+<li><code>#2aabee</code></li>
+
+
+
+<li><code>#2ee5ae</code></li>
+
+
+
+<li><code>#6afd6a</code></li>
+
+
+
+<li><code>#c0ee3d</code></li>
+
+
+
+<li><code>#feb927</code></li>
+
+
+
+<li><code>#fe6e1a</code></li>
+
+
+
+<li><code>#c2270a</code></li>
+
+
+
+<li><code>#900c00</code></li>
+</ul>
+
+
+
+<p>Once rendered, we have:</p>
+
+
+
+<figure class="wp-block-image"><img decoding="async" src="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/images/turbo-colors.png" alt="image" referrerpolicy="no-referrer"></figure>
+
+
+
+<p>The <code>dark</code> theme only uses 6 colors (well, 5 as one if the default white for dark theme, or black for light theme). So here’s my selection:</p>
+
+
+
+<figure class="wp-block-table"><table><thead><tr><th>Terminal Color</th><th>Matching Color</th><th>protanopia</th><th>deuteranopia</th><th>tritanopia</th></tr></thead><tbody><tr><td><code>yellow</code></td><td><code>#feb927</code></td><td><code>#f9bb27</code></td><td><code>#fbbc23</code></td><td><code>#ffacb6</code></td></tr><tr><td><code>magenta</code></td><td><code>#4860e6</code></td><td><code>#a77fe5</code></td><td><code>#888ee4</code></td><td><code>#257e7d</code></td></tr><tr><td><code>green</code></td><td><code>#6afd6a</code></td><td><code>#fee16c</code></td><td><code>#fee16c</code></td><td><code>#fee16c</code></td></tr><tr><td><code>red</code></td><td><code>#c2270a</code></td><td><code>#bb8b16</code></td><td><code>#936a15</code></td><td><code>#ff6579</code></td></tr><tr><td><code>cyan</code></td><td><code>#2aabee</code></td><td><code>#34adee</code></td><td><code>#22afef</code></td><td><code>#34b4b5</code></td></tr><tr><td>Null color (white-ish)</td><td><code>#2ee5ae</code></td><td><code>#e8d0b0</code></td><td><code>#c6beb3</code></td><td><code>#4ddfe0</code></td></tr></tbody></table></figure>
+
+
+
+<p>I also used the <code>bold</code> on the <code>success</code> and I actually inverted the <code>error</code> so the background is <code>red</code> and the text is white. High contrast is usually a good helper where we’re limited with the possible colors.</p>
+
+
+
+<p>The result seems to be pretty much working in all situations:<img decoding="async" alt="image" src="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/images/get-pod-impaired-theme-1.png" referrerpolicy="no-referrer"></p>
+
+
+
+<figure class="wp-block-image"><img decoding="async" src="https://piratemakers.ca/posts/2024/04/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/images/describe-pod-impaired-theme.png" alt="image" referrerpolicy="no-referrer"></figure>
+
+
+
+<h3 class="wp-block-heading" id="using-the-themes">Using the themes</h3>
+
+
+
+<p>Finally, along the other 4 themes announced before, you can now use any of the new themes if you’re concerned by color blindness. They are:</p>
+
+
+
+<ul>
+<li>protanopia-dark</li>
+
+
+
+<li>protanopia-light</li>
+
+
+
+<li>deuteranopia-dark</li>
+
+
+
+<li>deuteranopia-light</li>
+
+
+
+<li>tritanopia-dark</li>
+
+
+
+<li>tritanopia-light</li>
+</ul>
+
+
+
+<p>Just set your env variables like:</p>
+
+
+
+<pre class="wp-block-code"><code class="">KUBECOLOR_PRESET=protanopia-dark kubecolor get pods
+</code></pre>
+
+
+
+<p>Bash</p>
+
+
+
+<p>or</p>
+
+
+
+<pre class="wp-block-code"><code class="">export KUBECOLOR_PRESET=protanopia-dark
+kubecolor get pods
+</code></pre>
+
+
+
+<p>Bash</p>
+
+
+
+<p>Or set it in your config file <code>~/.kube/color.yaml</code> like:</p>
+
+
+
+<pre class="wp-block-code"><code class="">preset: protanopia-dark
+</code></pre>
+
+
+
+<p>YAML</p>
+
+
+
+<h3 class="wp-block-heading" id="updating-the-theme">Updating the theme</h3>
+
+
+
+<p>As the Themes are pretty much a first iteration and a work in proress, please, feel free to comment and <a href="https://github.com/kubecolor/kubecolor/issues">open an issue</a> if you feel the current themes can be enhenced.</p>
+
+
+
+<p>Also, you can start creating your own theme, by modifying an existing one, then share it either in a <code>issue</code> or a <code>Pull Request</code>.</p>
+
+
+
+<p>Simply start from original theme file and add more customization to the <code>~/.kube/color.yaml</code> file:</p>
+
+
+
+<pre class="wp-block-code"><code class="">preset: protanopia-dark
+theme:
+ base:
+ key:
+ - fg=#feb927
+ - fg=white
+ info:
+ primary: fg=#4860e6
+ secondary: fg=#2aabee
+ success: fg=#6afd6a:bold
+ warning: fg=#feb927
+ danger: fg=white:bg=#c2270a
+ muted: fg=#feb927
+ options:
+ flag: fg=#feb927
+ table:
+ header: fg=white:bold:bg=#2aabee
+ status:
+ error: fg=white:bg=#c2270a
+</code></pre>
+
+
+
+<p>YAML</p>
+
+
+
+<p>Note that, at the moment, all protanopia, deuteranopia and tritanopia themes are the same. Please, when you leave a feedback, mention your condition, so we can update the themes differently to better suite each of the different situations.</p>
+
+
+
+<p>I would encourage you to set your default theme according to your type of disability to benefit of the futur changes.</p>
+
+
+
+<h2 class="wp-block-heading" id="wrapping-it-up">Wrapping it up</h2>
+
+
+
+<p>Next time you see the screen of a co-worker using strange colors, don’t smile or make fun, this person is probably suffering some sort of color blindness. Instead, just explain them that KubeColor is now your friend.</p>
+
+
+
+<p>Even worse, the next time you see someone using <code>kubectl</code> in monochrome, <em>insist</em> for them to go check <a href="https://github.com/kubecolor/kubecolor">Kubecolor</a> !</p>
+
+
+
+<p>We put a lot of effort into this feature. We trully hope that it will help some persons out there and make Kubernetes more inclusive. If not, it was a good adventure.</p>
+
+
+
+<p>Feature is available in <a href="https://github.com/kubecolor/kubecolor/releases/tag/v0.3.0">Kubecolor v0.3.0</a>, available now !</p>
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+
+
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+https://www.cncf.io/blog/2024/05/06/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/https://www.cncf.io/blog/2024/05/06/adding-color-blind-themes-to-kubecolor-to-make-kubernetes-more-inclusive/Sun, 05 May 2024 16:00:00 GMTTop 5 cloud computing trends of 2024<p><em>Member post by Sameer Danave, Senior Director of Marketing, <a href="https://www.msystechnologies.com/">MSys Technologies</a></em></p>
+
+
+
+<p>Every time I think I have this whole technology game down to a science, something changes in the blink of an eye. And if you’re as enthusiastic about the cloud as I am, you’ve likely experienced the same feeling of whiplash as cloud trends continue to shift.</p>
+
+
+
+<p>Keeping up with the latest technology trends isn’t always easy. However, to stay ahead of the competition, it’s pivotal to stay ahead of them.</p>
+
+
+
+<p>Fortunately, I’ve gathered all the information you need on the latest cloud computing trends straight from industry experts and MSys’ survey of 400+ technology professionals and crafted a <a href="https://www.msystechnologies.com/technology-trends-2024/">Tech Lens 2024 </a>guide just for you. Let’s delve into the top five trends from this guide for 2024. </p>
+
+
+
+<h2 class="wp-block-heading"><strong>Top 5 Key Cloud Computing Trends to Watch</strong></h2>
+
+
+
+<p>Here are top five trends that are expected to witness significant traction in the forthcoming years. </p>
+
+
+
+<h3 class="wp-block-heading"><strong>AI As A Service (AIaaS)</strong></h3>
+
+
+
+<p>In the forthcoming years, significant growth is foreseen in the integration of AI services into cloud solutions. Cloud infrastructure plays a crucial role in opening up AI’s economic and social benefits to enterprises. Training AI models, such as the robust large language model (LLM) powering ChatGPT, demands extensive data and substantial computing resources. </p>
+
+
+
+<p>Enterprises are shifting away from constructing their own AI infrastructure and opting for AI-as-a-service provided by cloud platforms. This transition allows them to harness the transformative power of AI without the constraints of managing resources. AI as a Service offers pre-built AI models, tools, and APIs hosted on cloud platforms, enabling enterprises to seamlessly implement AI functionalities, even without specialized AI expertise and infrastructure.</p>
+
+
+
+<h3 class="wp-block-heading"><strong>Hybrid & Multi-Cloud Strategies</strong></h3>
+
+
+
+<p>Multi-cloud and hybrid solutions have become incredibly popular among enterprises across the globe. The hybrid multi-cloud approach incorporates public cloud services from multiple providers, enabling portability across diverse cloud infrastructures. This enhances flexibility and reduces dependency on a single vendor, thus mitigating the risk of vendor lock-in. </p>
+
+
+
+<p>Besides, hybrid cloud solutions offer a flexible approach to managing data storage complexities. By integrating public and private cloud environments, organizations can leverage existing infrastructure while gaining scalability, security, and redundancy. This approach optimizes storage resource allocation, strengthens disaster recovery capabilities, and fosters agility in response to evolving business requirements. </p>
+
+
+
+<p>Moreover, hybrid cloud solutions provide enhanced control over IT infrastructure and bolstered security compared to alternative cloud options. Cloud vendors employ expert security professionals to ensure data protection, adhering to stringent protocols and compliance measures.</p>
+
+
+
+<h3 class="wp-block-heading"><strong>Edge AI Computing</strong></h3>
+
+
+
+<p>The edge computing landscape is expected to witness significant traction in the forthcoming years. In the traditional cloud model, data transfers to a remote server for processing. In contrast, edge computing establishes a compact computing environment near the data source. </p>
+
+
+
+<p>This reduces latency and enables real-time analysis and decision-making. The deployment of advanced networks like 5G, along with energy-efficient processors and algorithms, is expected to further bolster edge computing’s viability for evolving application needs by 2024.</p>
+
+
+
+<h3 class="wp-block-heading"><strong>Sustainable Cloud Computing</strong></h3>
+
+
+
+<p>Sustainable computing is expected to experience significant growth in the years ahead. This trend is fueled by the understanding that approximately <a href="https://www.sciencedirect.com/science/article/pii/S2666389921001884">1.8% to 3.9%</a> of global greenhouse gas emissions stem from the information and communication technology (ICT) sector. </p>
+
+
+
+<p>Green computing encompasses environmentally conscious practices across the lifecycle of computers, chips, and other technology components, spanning from design and manufacturing to usage and disposal. Its objective is to mitigate environmental impact by decreasing carbon emissions and energy consumption across all stages, including production, data centers, and end-user operations. </p>
+
+
+
+<p>Additionally, green computing involves the selection of sustainably sourced materials, minimizing electronic waste, and promoting sustainability through the use of renewable resources.</p>
+
+
+
+<h3 class="wp-block-heading"><strong>Serverless Computing</strong></h3>
+
+
+
+<p>Expected to see significant expansion with a Compound Annual Growth Rate (CAGR) of <a href="https://www.mordorintelligence.com/industry-reports/serverless-computing-market">23.17%</a> between 2023 and 2028, serverless computing brings forth novel methods for creating and operating software applications and services. This emerging paradigm eradicates the necessity of infrastructure management, empowering users to write and deploy code devoid of the complexities of underlying systems. </p>
+
+
+
+<p>This transition offers numerous benefits for developers, including quicker time-to-market, improved scalability, and decreased deployment costs for new services. As a result, developers can focus on innovation rather than the intricacies of managing infrastructure.</p>
+
+
+
+<h2 class="wp-block-heading"><strong>Conclusion</strong></h2>
+
+
+
+<p>In the whirlwind of technological advancement, keeping pace with cloud computing trends is both exhilarating and essential. Drawing from insights of industry experts and a survey of over 400 technology professionals by MSys, we’ve distilled the top five trends for 2024. From AI integration to sustainable practices and serverless architectures, these trends promise to reshape our approach to technology. By embracing them, we can propel our organizations forward and stay ahead of the competition. This guide offers actionable insights to navigate these trends effectively. Let’s embark on this journey together, pushing the boundaries of cloud computing’s possibilities.</p>
+
+
+
+<p><strong>About Sameer</strong></p>
+
+
+
+<p> Sameer is a seasoned technology marketing professional with 16 years of full-stack marketing experience. He believes in 2 Cs – ‘Customer Value’ and Communications. All his Marketing campaigns and projects are packaged with it.</p>
+
+
+
+<p>He drives phygital (physical + digital) campaigns that attract and pull customers towards the brand’s value. His marketing strategies apply omnichannel, conversational marketing tactics (Storytelling, Social, and Chatbot), AI-Enabled Inbound Marketing, backed by solid analytics and insights with ‘content’ as a core part of the strategy.</p>
+
+
+
+<p>Sameer is a team sport with meticulous planning, attention to detail, and the ability to perform effortlessly under pressure.</p>
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+
+
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+https://www.cncf.io/blog/2024/05/03/top-5-cloud-computing-trends-of-2024/https://www.cncf.io/blog/2024/05/03/top-5-cloud-computing-trends-of-2024/Thu, 02 May 2024 16:00:00 GMTIs your supply chain secure? Double check with our framework<p>A secure supply chain is a critical piece of cloud native security, and it can be tricky to get right because it covers such a broad expanse of factors from code to pipelines and beyond.</p>
+
+
+
+<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
+<h2 class="wp-block-heading"><strong>Join us on June 26 & 27 for </strong><a href="https://events.linuxfoundation.org/cloudnativesecuritycon-north-america/?__hstc=60185074.e6eb4c023f39b99a65c0c9aa83f38c05.1714401528294.1714401528294.1714685072432.2&__hssc=60185074.1.1714685072432&__hsfp=4098832003"><strong>CloudNativeSecurityCon North America 2024</strong></a><strong> in Seattle</strong></h2>
+</blockquote>
+
+
+
+<p>The breadth of the supply chain also makes it vulnerable, and according to a survey from Security Magazine, <a href="https://www.securitymagazine.com/articles/100402-91-of-organizations-faced-a-software-supply-chain-attack-last-year#:~:text=91%25%20of%20organizations%20faced%20a%20software%20supply%20chain%20attack%20last%20year,-By%20Security%20Staff&text=According%20to%20a%20recent%20report,attack%20over%20the%20last%20year.">91% of organizations</a> experienced attacks in 2023. The top three types of attacks were exploited vulnerabilities or misconfigurations, stolen secrets, and data breaches. The reverberations of a supply chain attack go far beyond the organization and include reputational damage, loss of revenue, and even legal liability. In fact, IBM’s <a href="https://www.ibm.com/reports/data-breach">2023 “Cost of a Data Breach”</a> survey found attackers cost organizations worldwide an average of $4.45 million, which is a 15% increase over the last three years. </p>
+
+
+
+<p>Not surprisingly 51% of survey respondents told IBM their organizations were planning to increase spending on security.</p>
+
+
+
+<p>So, no matter where your organization is on the journey to a more secure supply chain, taking extra steps is never a bad idea. Our Security Technical Advisory Group has created a series of questions teams can ask to dig deeper. The framework is divided into four areas: source code, materials, build pipelines, and artefacts and deployments.</p>
+
+
+
+<p>Start by <a href="https://github.com/cncf/tag-security/blob/main/supply-chain-security/supply-chain-security-paper/secure-supply-chain-assessment.md#verify-source-code">verifying the source code</a>, asking questions including: </p>
+
+
+
+<ul>
+<li>Do you require signed commits?</li>
+
+
+
+<li>Do you use git hooks or automated scans to prevent committing secrets to source control?</li>
+
+
+
+<li>Have you defined an unacceptable risk level for vulnerabilities? For example: no code may be committed that includes Critical or High vulnerabilities</li>
+</ul>
+
+
+
+<p>Next, <a href="https://github.com/cncf/tag-security/blob/main/supply-chain-security/supply-chain-security-paper/secure-supply-chain-assessment.md#verify-materials">verify materials</a>:</p>
+
+
+
+<ul>
+<li>Do you verify that dependencies meet your minimum thresholds for quality and reliability?</li>
+
+
+
+<li>Do you automatically scan dependencies for security issues and license compliance?</li>
+
+
+
+<li>Do you automatically perform Software Composition Analysis on dependencies when they are downloaded/installed?</li>
+</ul>
+
+
+
+<p>Make certain <a href="https://github.com/cncf/tag-security/blob/main/supply-chain-security/supply-chain-security-paper/secure-supply-chain-assessment.md#protecting-build-pipelines">the build pipelines are protected</a>:</p>
+
+
+
+<ul>
+<li>Do you use hardened, minimal containers as the foundation for your build workers?</li>
+
+
+
+<li>Do you maintain your build and test pipelines as Infrastructure-as-Code?</li>
+
+
+
+<li>Do you automate every step in your build pipeline outside of code reviews and final sign-offs?</li>
+</ul>
+
+
+
+<p>And finally, <a href="https://github.com/cncf/tag-security/blob/main/supply-chain-security/supply-chain-security-paper/secure-supply-chain-assessment.md#protecting-artefacts-and-deployments">protect artefacts and deployments</a>: </p>
+
+
+
+<ul>
+<li>Is every artefact you produce (including metadata and intermediate artefacts) signed?</li>
+
+
+
+<li>Do you distribute metadata in a way that can be verified by downstream consumers of your products?</li>
+</ul>
+
+
+
+<p><a href="https://github.com/cncf/tag-security/blob/main/supply-chain-security/supply-chain-security-paper/secure-supply-chain-assessment.md">Dive into the entire framework</a>, but don’t stop there!</p>
+
+
+
+<p>Join us in Seattle for <a href="https://events.linuxfoundation.org/cloudnativesecuritycon-north-america/">CloudNativeSecurityCon North American 2024</a> on June 26 and 27 to learn from and network with experts in every facet of cloud native security.</p>
+
+
+
+<h3 class="wp-block-heading"><a href="https://events.linuxfoundation.org/cloudnativesecuritycon-north-america/register/">Register</a>! <a href="https://events.linuxfoundation.org/cloudnativesecuritycon-north-america/?__hstc=60185074.e6eb4c023f39b99a65c0c9aa83f38c05.1714401528294.1714401528294.1714685072432.2&__hssc=60185074.1.1714685072432&__hsfp=4098832003">Learn more</a>!</h3>
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+
+
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+https://www.cncf.io/blog/2024/05/03/is-your-supply-chain-secure-double-check-with-our-framework/https://www.cncf.io/blog/2024/05/03/is-your-supply-chain-secure-double-check-with-our-framework/Thu, 02 May 2024 16:00:00 GMTEarly explorations and practices of Xline, a stateful application managed by Karmada<p><em>Member post by DatenLord</em></p>
+
+
+
+<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1400" height="600" src="https://www.cncf.io/wp-content/uploads/2024/05/image-8.jpeg" alt="Early Explorations and Practices of Xline, a Stateful Application managed by Karmada banner by DatenLord and Xline" class="wp-image-106762" srcset="https://www.cncf.io/wp-content/uploads/2024/05/image-8.jpeg 1400w, https://www.cncf.io/wp-content/uploads/2024/05/image-8-300x129.jpeg 300w, https://www.cncf.io/wp-content/uploads/2024/05/image-8-1024x439.jpeg 1024w, https://www.cncf.io/wp-content/uploads/2024/05/image-8-768x329.jpeg 768w, https://www.cncf.io/wp-content/uploads/2024/05/image-8-900x386.jpeg 900w, https://www.cncf.io/wp-content/uploads/2024/05/image-8-467x200.jpeg 467w, https://www.cncf.io/wp-content/uploads/2024/05/image-8-933x400.jpeg 933w" sizes="(max-width: 1400px) 100vw, 1400px" referrerpolicy="no-referrer"></figure>
+
+
+
+<p><strong>Background and Motivation</strong></p>
+
+
+
+<p>More and more IT vendors are now embracing cross-cloud multi-clustering as cloud-native technologies and cloud markets continue to mature. Here’s Flexera’s mid-2023 survey on the cloud-native market’s acceptance of multi-cloud, multi-cluster management. (info.flexera.com)</p>
+
+
+
+<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="601" height="401" src="https://www.cncf.io/wp-content/uploads/2024/05/image-11.png" alt="Diagram showing State of the Cloud Report by flexera" class="wp-image-106763" srcset="https://www.cncf.io/wp-content/uploads/2024/05/image-11.png 601w, https://www.cncf.io/wp-content/uploads/2024/05/image-11-300x200.png 300w" sizes="(max-width: 601px) 100vw, 601px" referrerpolicy="no-referrer"></figure>
+
+
+
+<p>As you can see from Flexera’s report, more than 87 percent of organizations in the overall cloud-native market are already using services from multiple cloud vendors at the same time, with only 13 percent using a single public cloud and a single private cloud. Only 13% are using a single public cloud or single private cloud, while 15% of those using multi-cloud deployments are choosing multi-public or multi-private cloud deployments, and 72% are adopting hybrid cloud deployments. These statistics reflect the maturity of cloud-native technologies and the cloud marketplace, and the future will be the era of programmatic multi-cloud managed services.</p>
+
+
+
+<p>As you can see from Flexera’s report, more than 87 percent of organizations in the overall cloud-native market are already using services from multiple cloud vendors at the same time, with only 13 percent using a single public cloud and a single private cloud. Only 13% are using a single public cloud or single private cloud, while 15% of those using multi-cloud deployments are choosing multi-public or multi-private cloud deployments, and 72% are adopting hybrid cloud deployments. These statistics reflect the maturity of cloud-native technologies and the cloud marketplace, and the future will be the era of programmatic multi-cloud managed services.</p>
+
+
+
+<p>In addition to external trends, the limitations of single-cluster deployments have become an intrinsic motivation for users to embrace multi-cloud, multi-cluster management. Limitations of single cluster deployments include, but are not limited to:</p>
+
+
+
+<ul>
+<li>A single point of failure, where cluster-level failures are difficult to tolerate, and a small cluster federation outperforms a large K8s cluster.</li>
+
+
+
+<li>Boundary constraints of a single cluster, e.g., a Node has only 110 Pods by default, and a cluster can hold up to 5000 Nodes.</li>
+
+
+
+<li>Business-level development needs, e.g., Xline itself is a cross-cluster cluster.</li>
+
+
+
+<li>….</li>
+</ul>
+
+
+
+<p>Karmada, as an open source multi-cluster management tool, has been used by Shopee, DaoCloud and other companies in the production environment. However, since Karmada currently lacks support for stateful application management, it is still mainly used for stateless application management in practice.</p>
+
+
+
+<p>To better cope with the future trend of multi-cloud and multi-cluster management, and to better manage stateful applications in multi-cloud and multi-cluster scenarios, Xline and the Karmada community set up a working group to jointly promote Karmada’s support for stateful application management.</p>
+
+
+
+<p><strong>What are the challenges of managing stateful applications with Karmada?</strong></p>
+
+
+
+<p>Before understanding how Karmada manages stateful applications across multiple clusters, we need to look back at the K8s implementation of managing stateful applications in a single cluster.</p>
+
+
+
+<p>Back in 2012, Randy Bias gave an influential talk on “Open and Scalable Cloud Architecture”. In that talk, he proposed a “Pets” versus a “Cattle”.</p>
+
+
+
+<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1400" height="593" src="https://www.cncf.io/wp-content/uploads/2024/05/image-12.png" alt="A picture of cat and five cows" class="wp-image-106765" srcset="https://www.cncf.io/wp-content/uploads/2024/05/image-12.png 1400w, https://www.cncf.io/wp-content/uploads/2024/05/image-12-300x127.png 300w, https://www.cncf.io/wp-content/uploads/2024/05/image-12-1024x434.png 1024w, https://www.cncf.io/wp-content/uploads/2024/05/image-12-768x325.png 768w, https://www.cncf.io/wp-content/uploads/2024/05/image-12-900x381.png 900w, https://www.cncf.io/wp-content/uploads/2024/05/image-12-472x200.png 472w, https://www.cncf.io/wp-content/uploads/2024/05/image-12-944x400.png 944w" sizes="(max-width: 1400px) 100vw, 1400px" referrerpolicy="no-referrer"></figure>
+
+
+
+<p>These two concepts correspond to stateless and stateful applications, respectively. Cattle don’t need names, and they are not unique. This means we can easily replace one with another when one of them has some problems. Pets are different. Each pet is unique, with its own name, and should be looked after carefully when it has some problems.</p>
+
+
+
+<p>StatefulSet was introduced in Kubernetes 1.5 and stabilized in version 1.9. It provides a fixed Pod identity for managing Pods, persistent storage for each Pod, and a strict start/stop order among Pods.</p>
+
+
+
+<p>The problems are: what exactly constitutes a state, and how Kubernetes addresses it.</p>
+
+
+
+<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/QSNaB44hc0WhUQNxkR8cQejjgqWIFGCZ_qBVSXi-N3FWF0prS3vTq75-sVS-gG9I_rr-8dT44zNx8fx9AvonRq2-z3ZSgLWl7GhpwFVwWAUtqZciWHy53wnOVCNvqZdDyKkEFC_qBCe4nyri3ZukOw" alt="A screenshot of a white backgroundDescription automatically generated" referrerpolicy="no-referrer"></figure>
+
+
+
+<p>In the Karmada multi-cluster scenario, stateful applications pose the following problems:</p>
+
+
+
+<ol>
+<li>How to ensure that multiple application instances across clusters can have a globally uniform start/stop order, which affects the scale in/out and rolling updates of some application instances. For a distributed KV storage based on consensus protocol, the process of scale in/out needs to go through membership change, which involves the determination of majority change in the cluster. If multiple member clusters scale out at the same time without a globally standardized ordering, it will affect the correctness of the consensus reached by the consensus protocol.</li>
+
+
+
+<li>How to ensure that all applications across clusters have globally unique instance identifiers, a natural solution is to incorporate member cluster ids into instance identifiers.</li>
+
+
+
+<li>How to solve the problem of cross-cluster application communication and provide a globally uniform network identity. Currently, in our attempts and practices, we use submariners to bridge the network communication between multiple member clusters. The current implementation relies on a specific network plugin.</li>
+
+
+
+<li>How to solve the common functions such as cross-cluster stateful application update and capacity expansion and contraction, and provide more fine-grained update policies, such as realizing the function of Partition Update in member clusters.</li>
+</ol>
+
+
+
+<p>In order to better solve the above-mentioned problems, we need to introduce a new workload on Karmada to implement a cross-cluster version of “StatefulSet”.</p>
+
+
+
+<p><strong>Some early attempts at Xline</strong></p>
+
+
+
+<p>Since the Karmada community has not yet discussed the implementation details of the new API, we have made some simple attempts to deploy, scale up and down, and update Xline under Karmada. The overall architecture of the program is as follows:</p>
+
+
+
+<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1068" height="782" src="https://www.cncf.io/wp-content/uploads/2024/05/image-13.png" alt="Diagram flow showing Karmada architecture" class="wp-image-106766" srcset="https://www.cncf.io/wp-content/uploads/2024/05/image-13.png 1068w, https://www.cncf.io/wp-content/uploads/2024/05/image-13-300x220.png 300w, https://www.cncf.io/wp-content/uploads/2024/05/image-13-1024x750.png 1024w, https://www.cncf.io/wp-content/uploads/2024/05/image-13-768x562.png 768w, https://www.cncf.io/wp-content/uploads/2024/05/image-13-900x659.png 900w, https://www.cncf.io/wp-content/uploads/2024/05/image-13-273x200.png 273w, https://www.cncf.io/wp-content/uploads/2024/05/image-13-546x400.png 546w" sizes="(max-width: 1068px) 100vw, 1068px" referrerpolicy="no-referrer"></figure>
+
+
+
+<p>In the overall architecture, we adopt a two-tier Operator approach, in the control plane of Karmada, we deploy a Karmada Xline Operator, which is responsible for interpreting and splitting some Xline resources defined in Karmada, and sending them to member clusters. The Xline Operator on the member cluster monitors the creation of the corresponding resource and then enters the Reconcile process to complete the operation.</p>
+
+
+
+<p><strong>Deployment</strong></p>
+
+
+
+<p>Let’s take a look at a common deployment method for distributed application clusters under a single cluster (using etcd operator to deploy an etcd cluster as an example). etcd-operator can deploy an etcd cluster in two phases:</p>
+
+
+
+<ol>
+<li>Bootstrap: Create a seed node of etcd with an initial-cluster-state of new and a unique initial-clsuter-token.</li>
+
+
+
+<li>Scale out: perform a member add on the seed cluster to update the cluster network topology, and then start a new etcd node with an updated network topology and an initial-cluster-state of existing.</li>
+</ol>
+
+
+
+<p>However, in the cross-cluster scenario, due to the lack of a globally standardized startup order for pods in different member clusters, Xline Operators in different member clusters will concurrently perform cluster expansion operations, which will adversely affect the membership change process of the consensus protocol. In order to bypass this problem, Xline adopts a static deployment method, as shown in the following figure:</p>
+
+
+
+<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1290" height="836" src="https://www.cncf.io/wp-content/uploads/2024/05/image-14.png" alt="Diagram flow showing karmada resource scheme" class="wp-image-106767" srcset="https://www.cncf.io/wp-content/uploads/2024/05/image-14.png 1290w, https://www.cncf.io/wp-content/uploads/2024/05/image-14-300x194.png 300w, https://www.cncf.io/wp-content/uploads/2024/05/image-14-1024x664.png 1024w, https://www.cncf.io/wp-content/uploads/2024/05/image-14-768x498.png 768w, https://www.cncf.io/wp-content/uploads/2024/05/image-14-900x583.png 900w, https://www.cncf.io/wp-content/uploads/2024/05/image-14-309x200.png 309w, https://www.cncf.io/wp-content/uploads/2024/05/image-14-617x400.png 617w" sizes="(max-width: 1290px) 100vw, 1290px" referrerpolicy="no-referrer"></figure>
+
+
+
+<p>First of all, users need to define the corresponding resources on karmada to describe the cluster topology of a cross-cluster Xline cluster. karmada Xline Operator, after monitoring the resources being applied, will interpret and split the resources into the CR of XlineCluster on the member cluster, and then issue the CR of XlineCluster to the member cluster. The XlineCluster CR contains the number of replicas that should be created for the current member cluster, as well as the member cluster ids of the other clusters and the corresponding number of replicas. The Xline Operator on the member cluster, after monitoring the creation of the CR, will enter the Reconcile process to generate the DNS names of the other nodes in the Xline cluster using the issued cluster topology, and start the Xline Pod.</p>
+
+
+
+<p>In the early days of exploration, the static deployment approach bypassed the lack of a globally uniform startup order for application instances under Karmada’s multiple clusters because it did not involve a membership change in the deployment process. However, there is no silver bullet in the software industry, and the same is true for static deployments, which have some trade-offs as follows. The following table compares the characteristics of dynamic and static deployments in a single cluster vs. multi-cluster scenario:</p>
+
+
+
+<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1400" height="1199" src="https://www.cncf.io/wp-content/uploads/2024/05/image-15.png" alt="Table showing description of single cluster and multi-cluster on dynamic deployment and static deployment" class="wp-image-106768" srcset="https://www.cncf.io/wp-content/uploads/2024/05/image-15.png 1400w, https://www.cncf.io/wp-content/uploads/2024/05/image-15-300x257.png 300w, https://www.cncf.io/wp-content/uploads/2024/05/image-15-1024x877.png 1024w, https://www.cncf.io/wp-content/uploads/2024/05/image-15-768x658.png 768w, https://www.cncf.io/wp-content/uploads/2024/05/image-15-900x771.png 900w, https://www.cncf.io/wp-content/uploads/2024/05/image-15-234x200.png 234w, https://www.cncf.io/wp-content/uploads/2024/05/image-15-467x400.png 467w" sizes="(max-width: 1400px) 100vw, 1400px" referrerpolicy="no-referrer"></figure>
+
+
+
+<p><strong>Scaling Up and Down</strong></p>
+
+
+
+<p>There are two specific types of scale in/out for stateful applications under Karmada:</p>
+
+
+
+<ul>
+<li>Horizontal scale in/out — remove/add a member cluster and scale in/out nodes on it.</li>
+
+
+
+<li>Vertical scale in/out — scale in/out on existing member clusters.</li>
+</ul>
+
+
+
+<p><strong>Horizontal scale out</strong></p>
+
+
+
+<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1400" height="753" src="https://www.cncf.io/wp-content/uploads/2024/05/image-16.png" alt="Diagram flow showing Karmada control plane and multi-cluster service" class="wp-image-106769" srcset="https://www.cncf.io/wp-content/uploads/2024/05/image-16.png 1400w, https://www.cncf.io/wp-content/uploads/2024/05/image-16-300x161.png 300w, https://www.cncf.io/wp-content/uploads/2024/05/image-16-1024x551.png 1024w, https://www.cncf.io/wp-content/uploads/2024/05/image-16-768x413.png 768w, https://www.cncf.io/wp-content/uploads/2024/05/image-16-900x484.png 900w, https://www.cncf.io/wp-content/uploads/2024/05/image-16-372x200.png 372w, https://www.cncf.io/wp-content/uploads/2024/05/image-16-744x400.png 744w" sizes="(max-width: 1400px) 100vw, 1400px" referrerpolicy="no-referrer"></figure>
+
+
+
+<p>As shown above, the overall process is as follows:</p>
+
+
+
+<ol>
+<li>Create the corresponding member cluster, configure the submariner network, and add it to Karmada for management.</li>
+
+
+
+<li>Modify the Xline resources on Karmada, and add a new record member4: 4in the member cluster field to indicate that you want to expand 4 Xline resources on member4.</li>
+
+
+
+<li>Karmada Xline Operator will split the resources and distribute them to member4.</li>
+
+
+
+<li>Xline Operator on member4 receives the corresponding resources, enters the corresponding Reconcile process, calls the Xline client to execute member add, reaches a consensus, starts the new Xline Pod, and repeats the above process until the number of Xline replicas on member4 reaches the specified number. on member4 reaches the specified number</li>
+</ol>
+
+
+
+<p><strong>Vertical scale out</strong></p>
+
+
+
+<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1400" height="736" src="https://www.cncf.io/wp-content/uploads/2024/05/image-17.png" alt="Diagram flow showing Karmada control plane and multi-cluster service" class="wp-image-106770" srcset="https://www.cncf.io/wp-content/uploads/2024/05/image-17.png 1400w, https://www.cncf.io/wp-content/uploads/2024/05/image-17-300x158.png 300w, https://www.cncf.io/wp-content/uploads/2024/05/image-17-1024x538.png 1024w, https://www.cncf.io/wp-content/uploads/2024/05/image-17-768x404.png 768w, https://www.cncf.io/wp-content/uploads/2024/05/image-17-194x102.png 194w, https://www.cncf.io/wp-content/uploads/2024/05/image-17-388x204.png 388w, https://www.cncf.io/wp-content/uploads/2024/05/image-17-776x408.png 776w, https://www.cncf.io/wp-content/uploads/2024/05/image-17-900x473.png 900w, https://www.cncf.io/wp-content/uploads/2024/05/image-17-380x200.png 380w, https://www.cncf.io/wp-content/uploads/2024/05/image-17-761x400.png 761w, https://www.cncf.io/wp-content/uploads/2024/05/image-17-590x310.png 590w, https://www.cncf.io/wp-content/uploads/2024/05/image-17-1180x620.png 1180w" sizes="(max-width: 1400px) 100vw, 1400px" referrerpolicy="no-referrer"></figure>
+
+
+
+<p>For vertical scale out, the general process is also shown above:</p>
+
+
+
+<ol>
+<li>Modify the Xline resources on Karmada, e.g., specify that the Xline Pod in member1 should be expanded from 3 to 4</li>
+
+
+
+<li>Karmada Xline Operator will split the resource and distribute it to member1</li>
+
+
+
+<li>When Xline Operator on member1 receives the notification of resource modification, it enters the corresponding Reconcile process, calls the Xline client to perform member add, and then starts the new Xline Pod after consensus is reached, and repeats the above process until the number of replicas of Xline on member1 reaches the specified number. replicas of Xline on member1 reach the specified number</li>
+</ol>
+
+
+
+<p>Currently, because scale in/out inevitably involves a membership change process, and there is a lack of synchronization between member clusters under Karmada, there are limitations to the scale process: a horizontal scale out can only scale a cluster, and a vertical scale out can only scale a cluster on a specified member cluster.</p>
+
+
+
+<p><strong>Rolling updates</strong></p>
+
+
+
+<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="617" height="417" src="https://www.cncf.io/wp-content/uploads/2024/05/image-18.png" alt="Diagram flow showing Karmada control plane and multi-cluster service" class="wp-image-106771" srcset="https://www.cncf.io/wp-content/uploads/2024/05/image-18.png 617w, https://www.cncf.io/wp-content/uploads/2024/05/image-18-300x203.png 300w, https://www.cncf.io/wp-content/uploads/2024/05/image-18-296x200.png 296w, https://www.cncf.io/wp-content/uploads/2024/05/image-18-592x400.png 592w" sizes="(max-width: 617px) 100vw, 617px" referrerpolicy="no-referrer"></figure>
+
+
+
+<p>For a rolling update, the general process is shown above:</p>
+
+
+
+<ol>
+<li>The user modifies the Xline resource on Karmada to change the Xline mirror version.</li>
+
+
+
+<li>The Karmada Xline Operator splits the resource and distributes it to the member clusters.</li>
+
+
+
+<li>The Xline Operator on the member cluster monitors the resource changes and enters the corresponding Reconcile process to perform a rolling update. The update process on the member cluster is no different from the update on a single cluster.</li>
+</ol>
+
+
+
+<p>Currently, the main supported update method is the default rolling update, but from the perspective of practical application scenarios, at least the following two issues need to be considered:</p>
+
+
+
+<ol>
+<li>The update process involves the stopping of old Xline nodes and the starting of new Xline nodes, which requires additional mechanisms to ensure that the update process is not unavailable.</li>
+
+
+
+<li>More fine-grained update policies, such as Partition Update, should be supported; among multiple member clusters, priority should be given to updating clusters where only the follower exists, and when updating the member cluster where the leader resides, the leader should be transferred to the updated member cluster to avoid extreme situations where the leader frequently steps down due to rolling updates.</li>
+</ol>
+
+
+
+<p><strong>Conclusion</strong></p>
+
+
+
+<p>Given the trend of multi-cloud and multi-cluster management and the nature of Xline’s business, the Karmada and Xline communities have formed a working group to promote stateful application management in Karmada multi-clusters. In order to solve the problem of managing stateful applications in Karmada multi-clusters more elegantly, we need to introduce a new Karmada workload, and since the Karmada community has not yet reached a consensus on the implementation details of the new workload, in the early stage of experimentation, Xline adopts a two-tier Operator approach, which is implemented through the Karmada Xline Operator to the Karmada Xline Operator. The Karmada Xline Operator interprets and splits the top-level resources and sends them to the member clusters, and then the Xline Operator on the member clusters tunes the resources.</p>
+
+
+
+<p>In this way, we have made some early attempts to deploy Xline on Karmada and explore rolling updates, and made some preliminary preparations for the development and design of the new Karmada StatefulSet workload in the future.</p>
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+
+
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+https://www.cncf.io/blog/2024/05/02/early-explorations-and-practices-of-xline-a-stateful-application-managed-by-karmada/https://www.cncf.io/blog/2024/05/02/early-explorations-and-practices-of-xline-a-stateful-application-managed-by-karmada/Wed, 01 May 2024 16:00:00 GMTAccelerating Machine Learning with GPUs in Kubernetes using the NVIDIA Device Plugin<p><em>Member post originally published on the <a href="https://superorbital.io/blog/gpu-kubernetes-nvidia-device-plugin/">SuberOrbital blog</a> by Keegan McCallum</em></p>
+
+
+
+<h3 class="wp-block-heading"><em>NVIDIA Device Plugin for Kubernetes plays a crucial role in enabling organizations to harness the power of GPUs for accelerating machine learning workloads.</em></h3>
+
+
+
+<h2 class="wp-block-heading" id="introduction">Introduction</h2>
+
+
+
+<p>Generative AI is having a moment right now, in no small part due to the immense scale of computing resources being leveraged to train and serve these models. Kubernetes has <a href="https://superorbital.io/blog/the-cf-vs-k8s-vision-of-devops/">revolutionized the way we deploy and manage applications at scale</a>, making it a natural choice for building large-scale computing platforms.</p>
+
+
+
+<p>GPUs, with their parallel processing capabilities and high memory bandwidth, have become the go-to hardware for accelerating machine learning tasks. NVIDIA’s CUDA platform has emerged as the dominant framework for GPU computing, enabling developers to harness the power of GPUs for a wide range of applications. By combining the capabilities of Kubernetes with the extreme parallel computing power of modern GPUs like the NVIDIA H100, organizations are pushing the boundaries of what is possible with computers, from realistic video generation to analyzing entire novels worth of text and accurately answering questions about the contents.</p>
+
+
+
+<p>However, orchestrating GPU-accelerated workloads in Kubernetes environments presents its own set of challenges. This is where the NVIDIA Device Plugin comes into play. It seamlessly integrates with Kubernetes, allowing you to expose GPUs on each node, monitor their health, and enable containers to leverage these powerful accelerators. By combining these two best of breed solutions, organizations are building robust, performant computing platforms to power the next generation of intelligent software.</p>
+
+
+
+<h2 class="wp-block-heading" id="understanding-the-nvidia-device-plugin-for-kubernetes">Understanding the Nvidia Device Plugin for Kubernetes</h2>
+
+
+
+<p>The NVIDIA Device Plugin is a Kubernetes Daemonset that simplifies the management of GPU resources across a cluster. Its primary function is to automatically expose the number of GPUs on each node, making them discoverable and allocatable by the Kubernetes scheduler. This allows pods to request and consume GPU resources in a similar way to cpu and memory. Under the hood, the device plugin communicates with the kubelet on each node, providing information about the available GPUs and their capacities. It also monitors the health of the GPUs, ensuring they are functioning optimally and reporting any issues to Kubernetes.</p>
+
+
+
+<p>Some of the benefits of the NVIDIA Device Plugin include:</p>
+
+
+
+<ol>
+<li>Automatic GPU discovery and allocation, eliminating the need to manually configure GPUs resources on each node.</li>
+
+
+
+<li>Seamless integration with Kubernetes, allowing you to manage GPUs with familiar tools and workflows</li>
+
+
+
+<li>GPU health monitoring, allowing Kubernetes to maintain stability and reliability for GPU-accelerated workloads.</li>
+
+
+
+<li>Resource sharing, which allows multiple pods to utilize the same GPU, which is crucial in an environment like today where GPUs are scarce and expensive.</li>
+</ol>
+
+
+
+<h2 class="wp-block-heading" id="installing-and-configuring-the-nvidia-device-plugin">Installing and Configuring the Nvidia Device Plugin</h2>
+
+
+
+<h3 class="wp-block-heading" id="prerequisites">Prerequisites</h3>
+
+
+
+<ul>
+<li>Ensure that your GPU nodes have the necessary NVIDIA drivers (version ~= 384.81) installed.</li>
+
+
+
+<li><a href="https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html">Install the nvidia-container-toolkit</a> (version >= 1.7.0) on each GPU node.</li>
+
+
+
+<li><a href="https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#configuring-containerd-for-kubernetes">Configure the nvidia-container-runtime</a> as the default runtime for Docker or containerd.</li>
+
+
+
+<li>Kubernetes version >= 1.10</li>
+
+
+
+<li>If using AWS EKS for example, these will be handled for you by default when using GPU nodes</li>
+</ul>
+
+
+
+<h3 class="wp-block-heading" id="deploying-the-device-plugin">Deploying the Device Plugin</h3>
+
+
+
+<p>First, we’ll install the daemonset using <code>helm</code>. To install the latest version (v0.14.5 at the time of writing) into a cluster with default settings, the most basic command is:</p>
+
+
+
+<pre class="wp-block-code"><code class="">helm upgrade -i nvdp nvidia-device-plugin \
+ --repo https://nvidia.github.io/k8s-device-plugin \
+ --namespace nvidia-device-plugin \
+ --create-namespace \
+ --version v0.14.5
+</code></pre>
+
+
+
+<p>This will install OR upgrade a helm release named <code>nvdp</code> into the <code>nvidia-device-plugin</code> namespace, with default settings.</p>
+
+
+
+<p>This will give you a basic setup, but there are many reasons you may want to customize the chart via <code>values.yaml</code>. We’ll dive into some of the most useful options as well as some best practices, but you can see the full set of values <a href="https://github.com/NVIDIA/k8s-device-plugin/blob/v0.14.5/deployments/helm/nvidia-device-plugin/values.yaml">here</a>. You’ll likely want to add taints to your GPU nodes (the method used will depend on your kubernetes setup and how you are provisioning node) and then configure tolerations to ensure that the device plugin is only scheduled on GPU-enabled devices. We’ll dive deeper into these types of configurations in <a href="https://superorbital.io/blog/gpu-kubernetes-nvidia-advanced-troubleshooting/">part 2 of this series</a>.</p>
+
+
+
+<h3 class="wp-block-heading" id="configuring-gpu-sharing-and-oversubscription">Configuring GPU Sharing and Oversubscription</h3>
+
+
+
+<p>The <code>nvidia-device-plugin</code> supports 3 strategies for GPU sharing and oversubscription, allowing you to optimize GPU utilization based on your specific workload’s requirements. A quick overview of each, with examples of how to configure via <code>values.yaml</code>:</p>
+
+
+
+<ul>
+<li><strong>Time-slicing:</strong> This strategy allows multiple workloads to share a GPU by interleaving their execution. Each workload is allocated a specific time slice during which it has exclusive access to the GPU. Time-slicing is useful when you have many small workloads that don’t require the full power of a GPU simultaneously. One important point to note is that nothing special is done to isolate workloads that are granted replicas from the same underlying GPU, and each workload has access to the full GPU memory and runs in the same fault-domain as all of the others (<strong>meaning that if one pod’s workload crashes, they all do</strong>). In my experience, <strong>time-slicing usually isn’t what you’re looking for when it comes to GPU resource sharing</strong>, it’s basically just letting all the pods access the single GPU in a free-for-all manner and executing things concurrently without any regard for each other. If you have workloads that don’t mind this, such as Jupyter notebooks for research that aren’t utilizing the GPU at the same time, this setting COULD be useful, but I’d recommend looking at the other options first unless you know what you’re doing.Example <code>values.yaml</code> for time-slicing:</li>
+</ul>
+
+
+
+<pre class="wp-block-code"><code lang="javascript" class="language-javascript"><strong>config</strong>:
+ <strong>map</strong>:
+ <strong>default</strong>: |-
+ <strong>version</strong>: v1
+ <strong>sharing</strong>:
+ <strong>timeSlicing</strong>:
+ <strong>resources</strong>:
+ - <strong>name</strong>: nvidia.com/gpu
+ <strong>replicas</strong>: 10
+</code></pre>
+
+
+
+<ul>
+<li><strong>Multi-Instance GPUs (MIG):</strong> To mitigate the potential downsides of time-slicing, NVIDIA supports MIG. MIG is a feature supported on certain NVIDIA GPUs (e.g., A100) that enables partitioning a single GPU into multiple smaller, isolated instances. Each instance behaves like a separate GPU with its own memory and compute resources. MIG is beneficial when you have workloads with varying resource requirements and want to ensure strict isolation between them. This is in contrast to MPS which gives you more fine-grained control over memory and compute resource allocation, but doesn’t provide full memory protection and error isolation between them. MIG supports both <strong>mixed</strong> and <strong>single</strong> strategies for exposing GPUs to kubernetes, if interested you can read more about how they work <a href="https://docs.google.com/document/d/1mdgMQ8g7WmaI_XVVRrCvHPFPOMCm5LQD5JefgAh6N8g/edit#bookmark=id.vj44q8ogvavv">here</a>. Mixed is more flexible and I’d recommend using mixed unless you have a cluster large enough that exposing only a single MIG type per node is feasible. MIG is <a href="https://docs.nvidia.com/datacenter/tesla/mig-user-guide/index.html#supported-gpus">only supported on NVIDIA Ampere GPUs</a> and while less flexible than MPS, <strong><em>MIG is the most complete solution for workload isolation if your workloads require that.</em></strong>Example <code>values.yaml</code> for MIG:</li>
+</ul>
+
+
+
+<pre class="wp-block-code"><code lang="javascript" class="language-javascript"><strong>config</strong>:
+ <strong>map</strong>:
+ <strong>default</strong>: |<em>
+ version: v1
+ flags:
+ migStrategy: "mixed"</em>
+</code></pre>
+
+
+
+<ul>
+<li><strong>CUDA Multi-Process Service (MPS):</strong> MPS is a runtime service that enables multiple CUDA processes to share a single GPU context. It allows fine-grained sharing of GPU resources among multiple pods by running CUDA kernels concurrently. This mode feels the most similar to the way kubernetes can allocate cpu and memory resources in a fine-grained way, and is supported on almost every CUDA-compatible GPU. MPS will split up a GPU into equal slices of compute and memory, and the MPS control daemon will enforce these limits. Sharing with MPS is currently not supported on devices with MIG enabled. Sharing with MPS is currently not supported on devices with MIG enabled. MPS is suitable when you have workloads that can efficiently share GPU resources without strict isolation requirements. <strong><em>If you don’t have strict isolation requirements, MPS is probably the right choice for you.</em></strong>Example <code>values.yaml</code> for MPS:</li>
+</ul>
+
+
+
+<pre class="wp-block-code"><code lang="javascript" class="language-javascript"><strong>config</strong>:
+ <strong>map</strong>:
+ <strong>default</strong>: |-
+ <strong>version</strong>: v1
+ <strong>sharing</strong>:
+ <strong>mps</strong>:
+ <strong>resources</strong>:
+ - <strong>name</strong>: nvidia.com/gpu
+ <strong>replicas</strong>: 10
+</code></pre>
+
+
+
+<p>This should be a good introduction to GPU sharing to get you started. We will go into more detail about advanced configuration and best practices in part 2 of this series.</p>
+
+
+
+<h2 class="wp-block-heading" id="allocating-gpus-to-pods-using-the-nvidia-device-plugin">Allocating GPUs to Pods Using the Nvidia Device Plugin</h2>
+
+
+
+<p>Allocating GPUs to pods when using the <code>nvidia-device-plugin</code> is straightforward and should feel familiar to anyone comfortable with kubernetes. It is highly recommended to use NVIDIA base images for your containers in order to have all the necessary dependencies installed and configured properly for your underlying workload. Setting a limit for <code>nvidia.com/gpu</code> is crucial, otherwise all GPUs will be exposed inside the container. Finally, make sure to include <a href="https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/">tolerations</a> for any taints set on your nodes so that the pod can be scheduled appropriately. Here’s a barebones example of a GPU-enabled pod:</p>
+
+
+
+<pre class="wp-block-code"><code lang="javascript" class="language-javascript"><strong>apiVersion</strong>: v1
+<strong>kind</strong>: Pod
+<strong>metadata</strong>:
+ <strong>name</strong>: gpu-pod
+<strong>spec</strong>:
+ <strong>containers</strong>:
+ - <strong>name</strong>: cuda-container
+ <strong>image</strong>: nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda10.2
+ <strong>resources</strong>:
+ <strong>limits</strong>:
+ <strong>nvidia.com/gpu</strong>: 1 <em># requesting 1 GPU</em>
+ <strong>tolerations</strong>:
+ - <strong>key</strong>: nvidia.com/gpu
+ <strong>operator</strong>: Exists
+ <strong>effect</strong>: NoSchedule
+</code></pre>
+
+
+
+<h2 class="wp-block-heading" id="conclusion">Conclusion</h2>
+
+
+
+<p>The NVIDIA Device Plugin for Kubernetes plays a crucial role in enabling organizations to harness the power of GPUs for accelerating machine learning workloads. By abstracting the complexities of GPU management and providing seamless integration with Kubernetes, it empowers developers and data scientists to focus on building and deploying their models without worrying about the underlying infrastructure.</p>
+
+
+
+<p>We’re just scratching the surface here, so if you’re interested to learn more please check out part 2 of this series where we’ll go into detail on advanced configuration, troubleshooting common issues, and some of the limitations of using the <code>nvidia-device-plugin</code> alone to manage GPUs. Also, check out the additional resources at the end of this article!</p>
+
+
+
+<h2 class="wp-block-heading" id="further-reading-and-resources">Further Reading and Resources</h2>
+
+
+
+<ul>
+<li><a href="https://github.com/NVIDIA/k8s-device-plugin">Official NVIDIA Device Plugin Documentation</a></li>
+
+
+
+<li><a href="https://github.com/NVIDIA/k8s-device-plugin/blob/v0.14.5/deployments/helm/nvidia-device-plugin/values.yaml">NVIDIA Device Plugin Helm Chart Values</a></li>
+
+
+
+<li><a href="https://kubernetes.io/docs/tasks/manage-gpus/scheduling-gpus/">Kubernetes GPU Scheduling Documentation</a></li>
+
+
+
+<li><a href="https://docs.google.com/document/d/1mdgMQ8g7WmaI_XVVRrCvHPFPOMCm5LQD5JefgAh6N8g/edit">NVIDIA MIG Documentation</a></li>
+</ul>
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+
+
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+https://www.cncf.io/blog/2024/04/30/accelerating-machine-learning-with-gpus-in-kubernetes-using-the-nvidia-device-plugin/https://www.cncf.io/blog/2024/04/30/accelerating-machine-learning-with-gpus-in-kubernetes-using-the-nvidia-device-plugin/Mon, 29 Apr 2024 16:00:00 GMTFinOps for Kubernetes: engineering cost optimization<p><em>Community post by <a href="https://linkedin.com/in/s-jan">Saqib Jan</a></em></p>
+
+
+
+<p>Cloud has given on-demand access to compute resources, but high availability also makes cost a much more dynamic problem to forecast. This reverberates as companies continue to expand their cloud footprints and adopt more cloud technologies — the potential for waste also increases.</p>
+
+
+
+<p>The<a href="https://data.finops.org/"> 2024 State of FinOps report</a> underscores, organizations are focused on reducing waste. And with efficiencies top of mind, it is imperative that savings and cost optimization is the top priority for engineering leaders considering a FinOps model in Kubernetes. Because understanding how to estimate cost and optimization is a black hole for platform engineering and finance teams, the biggest challenge for stakeholders is figuring out where costs originate. So, to address this, some understanding of ownership costs is important.</p>
+
+
+
+<p>Big tech engineering teams with mature finance and product management practices are solving for these challenges with cost models that help measure the total cost of ownership of their services and applications.<a href="https://www.linkedin.com/in/laurentgil"> Laurent Gil</a>, Cloud Neutrality Advocate and Co-Founder of Cast AI, exposits that the cost model often isn’t sufficient for anything but an informed starting point—a good enough point must be reached to avoid over-investment.</p>
+
+
+
+<p>The first thing to consider is the cost drivers—elements that contribute to the overall cost and how to incorporate them into calculations. There is CPU, memory, and storage allocated to each service and execution in Kubernetes. Workloads also grow larger over time, and there are a variety of costs involved in hosting, integrating, running, managing, and securing cloud workloads. While some charges directly relate to compute, data transfer, and storage consumption, other factors add complexity. And there are also toolings as well as integrations with other cloud services that must be factored into the total cost of ownership (TCO) calculations.</p>
+
+
+
+<h2 class="wp-block-heading"><strong>Architect for Efficient Cloud Usage</strong></h2>
+
+
+
+<p>If you run Kubernetes yourself, you need to have a strong engineering team. And unless you are in a business close to containerization and microservices technology, it’s essentially just a cost center and an inefficient use of resources.</p>
+
+
+
+<p>It’s a very challenging task to build out Kubernetes yourself and being able to understand all the different nuances of all the different components that need to be set up and configured properly. And anyone who is not in the business of running infrastructure will basically benefit from managed Kubernetes. You don’t have to hire a team for anything which you want to run at any reasonable level of reliability.</p>
+
+
+
+<p>Richard Hartmann, Director of Community for<a href="https://grafana.com/"> Grafana Labs</a>, shares two fundamental ways to efficient cloud usage. One is to “go all-in on bespoke services, leveraging whatever you can to reduce undifferentiated heavy lifting and focus on solving problems that drive your business forward.” Alternatively, you can “use as few bespoke services as possible, relying solely on the baseline across all providers.” This approach allows you to maintain control over how your platform operates and facilitates easy migration between clouds. “Both approaches have merit,” but he cautions being in between is usually not ideal as it exposes you to the drawbacks of both tradeoffs.</p>
+
+
+
+<p>Both solutions have similar problems. Cloud is expensive, and there is zero incentive for cloud providers to offer great cost controls. Hartmann points out the inherent conflict of interest, underscoring, “that would literally enable users to pay less,” something no cloud provider would want, particularly in the current macroeconomic uncertainties, adding more pressure to engineering leaders already contending with shrinking budgets, and heightened expectations for cost efficiency.</p>
+
+
+
+<p>And so, there’s also a lot of interest from companies about trying to figure out what is the right model and how to find that happy balance between knowing not just what’s running in production but also how to set up a dev-test environment effectively.</p>
+
+
+
+<p>“A lot of our customers today are looking at different models internally for their projects that are running in the cloud through managed Kubernetes offerings, whether it be a showback or chargeback type model,” commented<a href="https://about.gitlab.com/"> GitLab</a> Field CTO Lee Faus. And he mentioned, “We’ve had a few customers who tried to implement quotas around what they’re allowed to spend using high water, low water marks. But in doing so<strong>,</strong> they’ve realized that because of the way most managed Kubernetes clusters work, they incentivize you to build things like auto-scaling.”</p>
+
+
+
+<p>There are more reasons why organizations end up in situations with over-provisioned clusters, which not only lead to poor cycle times from a CPU and memory perspective but also ultimately result in a negative experience for end-user interactions with the applications.</p>
+
+
+
+<p>To counteract the risk of uncontrolled spending, Hartmann says “we have implemented deep control over what specifically we do and built our cost controls for self-managed clusters and as well managed platforms.” This approach helps scrutinize operations, ultimately enforcing a chargeback program that encourages a shared sense of accountability across stakeholders.</p>
+
+
+
+<p>Both Hartmann and Faus highlight challenges in managing costs and finding the right balance between control and cost efficiency. FinOps practices, they affirm, help organizations to anticipate, control, check, and optimize their cloud investments on a proactive and reactive basis.</p>
+
+
+
+<h2 class="wp-block-heading"><strong>FinOps for Kubernetes Cost Control Strategies</strong></h2>
+
+
+
+<p>Cost management on the cloud side can get out of control, but a lot of that stems from not having good rigor in the software development lifecycle — where things are pushed into production before they’re actually ready, or when they haven’t been adequately tested from a performance perspective. And considering the business value, there has never been a more important time to adopt FinOps principles ‘inform, operate, and optimize’ because existing solutions do not capture the nuances needed to economically achieve the perfect balance between cost and performance.</p>
+
+
+
+<p>FinOps is the discipline to exhort shared responsibility and bring together all stakeholders (tech, business, and finance people) to establish policies and best practices for usage that are programmatically enforced. Adopting a FinOps approach can help platform engineering teams dramatically increase their visibility necessary to find ways to reduce costs without affecting performance.</p>
+
+
+
+<p>When DevOps, say for instance, gives developers tools and guardrails to build, deploy, and fully own an application, it’s important to also educate them about overall cost management. This is because empowering teams to take action is the top challenge. And it’s usually not until the bill comes due at the end of the month that finance teams realize there is an issue with sudden spikes in costs.</p>
+
+
+
+<p>I can tell you from supporting clients that most organizations leveraging Kubernetes struggle to manage their cloud expenses because there is no proper review and refining cycle for their processes, and also the pool of skilled workers in this segment is very dry.</p>
+
+
+
+<p>Faus, in our conversation, stipulated, “There’s a term that we’re starting to see a lot of companies use, which revolves around value streams.” Value streams allow us to map back to key performance indicators (KPIs). And, these KPIs are defined at the CEO, CIO, and CFO level, where budgets are drawn, resource hiring is planned, and new product lines are decided. “This provides a high-level mapping back to those elements and around those value streams. When we drive throughout the given year, we need to have a way to ensure that we are actively tracking these aspects throughout the SDLC and in our cost management.”</p>
+
+
+
+<p>Whatever you may call it, empowering development teams becomes imperative when using Kubernetes. Taking responsibility to make informed decisions will, in turn, make Kubernetes cost management timely, proactive, and cost-effective. As budgets get tighter, there is a great need for cost control strategies — to build from a knowledgeable foundation your own cost controls and implement a third-party solution, whether commercial or open source, to avoid linear cost increases. They are effective for everyone — for any cloud provider and even Kubernetes on bare metal infrastructure.</p>
+
+
+
+<h3 class="wp-block-heading"><strong>Case Study: LambdaTest</strong></h3>
+
+
+
+<p>A perfect example to showcase the lasting impact of FinOps practices can be seen with<a href="https://www.lambdatest.com/"> LambdaTest</a>. This young company, providing infrastructure as a cloud platform for online browser and operating system testing, quickly scaled up its services after securing initial funding but then encountered challenges with sudden spikes in cloud costs during subsequent rounds of funding.</p>
+
+
+
+<p>As the senior DevOps engineering leader,<a href="https://www.linkedin.com/in/shahid-ali-khan-2aa084a3/"> Shahid Ali Khan</a> led the responsible development of LambdaTest’s Kubernetes infrastructure and overall infrastructure system. He shared invaluable insights on navigating the exhaustive platform engineering challenges and adopting FinOps principles, imperative in the process, for optimizing cloud resources and saving cloud costs.</p>
+
+
+
+<p>This case study highlights LambdaTest’s journey to FinOps maturity, emphasizing cost optimization. And outlines a systematic approach with insights from notable leaders, to proactively navigate these hurdles. The study discusses technology solutions, strategies, outcomes, and lessons from my one-on-one interviews with these leaders.</p>
+
+
+
+<h4 class="wp-block-heading"><strong>— The Challenges of Managing Infrastructure</strong></h4>
+
+
+
+<p>As LambdaTest expanded their offerings, the complexity of their infrastructure also increased, relying on AWS and self-managed Kubernetes to support their data-heavy customers. This architecture allowed them to scale rapidly, and<a href="https://www.linkedin.com/in/muditsingh5000/"> Mudit Singh</a>, Head of Growth & Marketing, reflects their initial decision. “When we started off with Kubernetes, no cloud provider was offering a static, stable solution for it. And at that time, in around 2017, AWS released Managed Kubernetes, which remained in testing for an extended period. As a startup with a talent shortage, we were unsure about managing our own cluster.”</p>
+
+
+
+<p>As their usage increased, each month ended with sudden cost spikes that created more questions around spend, like ‘How much are we spending?’ ‘Is this normal?’ ‘How should cost be divided between teams, applications, and business units?’ and ‘What is the problem, over-provisioning, or using too much compute or memory?’ remained unanswered. This situation, Singh shares, “drained our DevOps leaders, platform engineering and Finance teams (including the Founders) to invest a significant amount of time and attention in understanding the hefty incoming invoices.”</p>
+
+
+
+<p>These issues even escalated over time — as usage grew, the risk of losing cost control also increased. The company sourced tools to produce cloud consumption but struggled to identify and address cost drivers. Like many, LambdaTest also faced challenges in the balancing act of trying to build a team with a FinOps culture and striving for enhanced cost visibility.</p>
+
+
+
+<p>Singh stressed how identifying and addressing the underlying problems driving up costs proved to be a struggle for them while managing data centers across continents. And Khan expounds on the cross-functional initiatives they took to gain clarity on cost drivers, achieving visibility and transparency into spending and cloud usage.</p>
+
+
+
+<h4 class="wp-block-heading"><strong>— Create a Tagging Framework</strong></h4>
+
+
+
+<p>It is difficult to align reports to business context without insight into workload allocations, and the industry has seen the adoption of more structured approaches to resource management.</p>
+
+
+
+<p>Khan detailed, “We have multiple products that are running, and there are services shared among those products. It was getting hard for us to identify which service is contributing—or which particular service is contributing—to the cost of each product.” Tagging with labels also helps identify over-provisioned resources. And, “we began by implementing tagging and labeling, along with utilizing different node pools. This enabled us to precisely determine the cost allocation for each product in terms of specific resources, understand how their requirements have scaled over time, and effectively address those needs.”</p>
+
+
+
+<p>It has now become a common practice to leverage namespaces for each product or service in Kubernetes, with a clear bifurcation of services. This approach not only lays the groundwork for resource management but also supports isolation, resource quotas, and simplified access control—enhancing operational efficiency. And most importantly makes cost analysis, reporting, and optimization easier for individual teams, services, or business lines.</p>
+
+
+
+<h4 class="wp-block-heading"><strong>— From Data to Action</strong></h4>
+
+
+
+<p>The volume of data subject to analysis for cost optimization is always considerable. Being able to vectorize that data and understand where there are errors, where there might be memory spikes, CPU spikes—these are areas where you can not only optimize for the cost structure of how to manage applications but also provide feedback to the engineering teams. Faus underlines, “This involves actions like automatically promoting an issue or a ticket on the product side to ensure that something is going to be done about that cost as part of a current sprint.”</p>
+
+
+
+<p>This process should also involve analyzing time-series data, which exceedingly helps to identify inefficiencies, make informed decisions about resource allocation and find potential automation opportunities. There are other strategies and optimization tactics you could adopt, but in general, at a basic level, it’s good to consider first what you are optimizing for.</p>
+
+
+
+<p>So what is optimizing for cost? It’s really just another metric to consider. Say, for example, I already manage CPUs, pods, memory, storage, and compute capabilities. Each one, then, is a piece of the larger puzzle I’m piecing together. So, adding cost into the mix doesn’t change the fundamental approach; it’s just integrating another element into the array of resources we’re already balancing.</p>
+
+
+
+<p>Khan emphasizes the key focus is on enabling “our tech personnel to efficiently extract and manipulate data to align with our business objectives, rather than the other way around. This strategy, which we also implement internally at LambdaTest, underscores the critical importance of fostering internal collaboration and knowledge exchange to effectively bridge the technological and business divides within our organization.”</p>
+
+
+
+<h4 class="wp-block-heading"><strong>— Cost Visibility</strong></h4>
+
+
+
+<p>The very important aspect of optimizing the cost and running the cluster without impacting the performance and usage is monitoring. It is the core pillar toward building awareness and informing FinOps objectives for optimization strategies.</p>
+
+
+
+<p>“We tried a lot of solutions and multiple plugins, but we could not get a clear understanding of the volume of requests, the performance of the cluster, or the overall system status,” Khan specified. “We implemented distributive tracking (and distributed tracing) inside the cluster to monitor each and every request, which helped us to identify how services are being used and pinpoint optimization opportunities within the system. This tremendously helped us to identify inefficiencies, which increased accountability – informing service owners to take action, while also enabling things like internal chargeback and showback models.”</p>
+
+
+
+<p>Visibility underpins FinOps metrics (idle resources, under-optimized infrastructure) for tracking progress. But the key metric to consider is normalized cost, which, when adjusted for your operating business metrics, provides a more holistic view of your cloud spending relative to your business activities.</p>
+
+
+
+<h4 class="wp-block-heading"><strong>— Drill-Down Granularity</strong></h4>
+
+
+
+<p>What you do next will depend on where your baseline is. But allowing issues to persist over time makes controlling costs at a later stage difficult and challenging. Even if you attempt to control them later, the level of effort required from your team would be very difficult, diverting focus from implementing features.</p>
+
+
+
+<p>It is here that a tagging framework with a Kubernetes cost management tool becomes helpful. This helps you drill down into the layers of your environment so you can see exactly how each application is impacting your costs, enabling proactive recommendations for cost savings.</p>
+
+
+
+<p>Khan shared their approach, “We began observing all attributes that influence pricing, and based on that, we looked deeper into why there has been an increase, what could have caused it, and then took rather difficult — educational path to show individual teams how their environment impacts their department’s resources.”</p>
+
+
+
+<p>The ideal solution, according to Khan’s recommendation, “should provide time-saving features.” An example would be a prioritized list of your environment’s most expensive components, ranked by cost. This allows you to focus on the areas that will yield the most significant cost savings first. “We realized this and implemented a proactive approach across teams, ensuring work could proceed in a manner that does not affect production.”</p>
+
+
+
+<h4 class="wp-block-heading">— <strong>Real-Time Alerting</strong></h4>
+
+
+
+<p>Now, in cloud-native environments with auto-scaling enabled, your cluster or nodes can scale up or down. Therefore, implementing budgets and alerts within the cloud system is imperative, as non-tracking can lead to significant expenses that won’t justify the solution you are providing. This is why applying custom rules programmatically allows you to receive notifications when costs increase, enabling you to take corrective actions for specific requests.</p>
+
+
+
+<p>Khan remarked, “FinOps practices have significantly changed the way we work.” Through extensive data analysis, “we measure costs to a significant extent and set budgets for each product. For example, each product has clusters, and some of them share services. With simple tagging, we can set specific budgets for each product. And when we allocate a certain amount to a product, we get alerts if spending goes over a predetermined threshold.” A small increase triggers an amber alert, and a big jump triggers a red alert.</p>
+
+
+
+<p>The optimal solution should also alert you to abnormal cost spikes in real-time so you can examine the issue right away and remediate it, rather than waiting for weekly or monthly reports. And sometimes, these spikes may serve as an early warning sign of a cyberattack, which requires an immediate and proactive response to safeguard your infrastructure and data integrity.</p>
+
+
+
+<h2 class="wp-block-heading"><strong>Encourage FinOps Practices</strong></h2>
+
+
+
+<p>The more intentional approach you take to plan for change, you’ll target places where change will be the most effective soonest. But the worst thing you could do as an organization is to say, ‘we’re going to inform’ without understanding the extent to which overspending is ingrained in your Ops and, importantly, where some of the key drivers are coming from.</p>
+
+
+
+<p>The best way to manage Kubernetes at scale is to take a holistic and intentional approach, which also helps in calculating the total cost of ownership and allocating budgets, but it is not something most companies are doing. Bifurcation of resources is not what most companies are doing either. A lot of companies are managing huge infrastructures, but what they lack is a dedicated FinOps team for such instances. And the reactive approach that they are taking for incidents, in terms of cost management, lead to significant financial burdens.</p>
+
+
+
+<p>Cloud lets you accelerate, but it can also be a double-edged sword without a proactive approach. According to the<a href="https://www.cncf.io/wp-content/uploads/2023/12/CNCF_Finops-Microsurvey-2023.pdf"> CNCF microsurvey report</a>, over provisioning or having more resources than necessary, is one of the most common factor leading to over-provisioning.</p>
+
+
+
+<p>“We’ve analyzed usage data on thousands of applications, and there are three primary reasons companies overspend: over-provisioning, pod requests being set too high, and low usage of Spot instances,” Gil enumerated. The biggest source of overspend, however, is an overestimation of the real CPU/memory usage. “For more than 97% of the applications we analyzed, the pre-optimized utilization of CPU is only 12%. That means that, on average, nearly 90% of compute is paid for, but goes unused.” And these percentages, he laid out, “are consistent across application sizes and cloud providers.”</p>
+
+
+
+<p>The underlying reason that causes most companies to overspend is the lack of education and empowerment. Tech, DevOps, and infrastructure teams often lack cost awareness. And change is not easy because to build the culture of transparency and openness requires sharing pricing information with engineers and creating a safe space for open communication.</p>
+
+
+
+<p>This is difficult for nearly all companies because people are first concerned about not stepping on anyone else’s toes. And it can be very unhelpful if fewer people are bold enough to be involved. The key is to get everyone on the same page regarding the business objectives. This means sharing the plan, how things are looking in the near future, what kind of services are planned for wider rollout, and even the company’s gross margin. “It is transparency that spurs on shared understanding,” Hartmann remarks. When everyone sees the bigger picture, they can feel the “real pain” of overspending and how their work directly impacts it. This shared understanding empowers team members to contribute to cost control strategies.</p>
+
+
+
+<p>Building on the strategies discussed, a Kubernetes governance platform can serve as an initial step to gain clarity into resource utilization and enable you to drill down into the various layers of your environment. It can also provide policy-based control for cloud-native environments, empowering teams to make informed financial decisions regarding Kubernetes by allowing them to grasp and adopt cost-control strategies.</p>
+
+
+
+<hr class="wp-block-separator has-alpha-channel-opacity">
+
+
+
+<p><strong>Author: </strong>Saqib Jan</p>
+
+
+
+<p><strong>Email: </strong><a href="mailto:sakimjan8@gmail.com">sakimjan8@gmail.com</a></p>
+
+
+
+<p><strong>LinkedIn: </strong><a href="https://linkedin.com/in/s-jan">https://linkedin.com/in/s-jan</a></p>
+
+
+
+<p><strong>BIO: </strong>Saqib Jan is a freelance analyst with experience in application development, cloud technologies, and consulting.</p>
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+
+
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+https://www.cncf.io/blog/2024/04/29/finops-for-kubernetes-engineering-cost-optimization/https://www.cncf.io/blog/2024/04/29/finops-for-kubernetes-engineering-cost-optimization/Sun, 28 Apr 2024 16:00:00 GMTThe hidden economy of open source software<p><em>Member post originally published on <a href="https://sysdig.com/blog/hidden-economy-of-open-source-software/">Sysdig’s blog</a> by Nigel Douglas</em></p>
+
+
+
+<p>The recent discovery of a <strong>backdoor in XZ Utils</strong> (<a href="https://sysdig.com/blog/cve-2024-3094-detecting-the-sshd-backdoor-in-xz-utils/">CVE-2024-3094</a>), a data compression utility used by a wide array of various open-source, Linux-based computer applications, underscores the importance of open-source software security. While it is often not consumer-facing, open-source software is a critical component of computing and internet functions, such as secure communications between machines.</p>
+
+
+
+<p>Open source software (abbreviated as OSS) has become a cornerstone of the tech industry, influencing everything from small startups to global corporations. Despite its ubiquitous presence and foundational role in driving innovation, the true economic value of OSS has remained largely uncharted territory—until now. A groundbreaking study entitled “<a href="https://www.hbs.edu/ris/Publication%20Files/24-038_51f8444f-502c-4139-8bf2-56eb4b65c58a.pdf">The Value of Open Source Software</a>” by researchers Manuel Hoffmann, Frank Nagle, and Yanuo Zhou at Harvard Business School delves into this unexplored domain, revealing the astonishing economic impact of OSS throughout industry.</p>
+
+
+
+<h2 class="wp-block-heading" id="h-a-priceless-foundation-with-a-trillion-dollar-impact">A Priceless Foundation with a Trillion-Dollar Impact</h2>
+
+
+
+<p>The study begins by addressing a fundamental paradox: How do you measure the value of something that is freely available? Traditionally, economic value is calculated by multiplying the price of a product by the quantity sold. However, this formula hits a snag when it comes to OSS—there’s no price tag on something that’s free, and tracking its usage is a Herculean task due to the decentralised nature of OSS distribution.</p>
+
+
+
+<p>Leveraging unique global data sources and a novel approach, the research estimates the “supply-side” value (the cost to recreate the most widely used OSS) at $4.15 billion. But the true eye-opener is the “demand-side” value, pegged at a staggering $8.8 trillion. This figure represents the hypothetical cost that companies would face if they had to develop equivalent software internally, highlighting the immense savings and efficiency gains OSS provides to the global economy.</p>
+
+
+
+<p>For instance, Falco, an open-source, cloud-native security tool, <a href="https://github.com/falcosecurity/falco/graphs/contributors">boasts contributions from 190 individuals</a> dedicated to enhancing the software and ensuring it meets the evolving threats in cloud computing. If an organisation attempted to develop a custom threat detection engine in Go from scratch, it would be financially impractical to employ 190 staff members to continuously develop and maintain the tool. Although most of the 190 contributors likely engage with Falco as a side project rather than their primary employment, acknowledging the number of people actively committing to the project offers valuable insight into its collective human investment.</p>
+
+
+
+<h3 class="wp-block-heading" id="h-the-unsung-heroes-of-oss">The Unsung Heroes of OSS</h3>
+
+
+
+<p>One of the most intriguing findings of the study is the concentration of value creation within the OSS community. A mere 5% of OSS developers are responsible for 96% of its demand-side value. This elite group of contributors has a disproportionate impact on the software landscape, emphasising the need for support and recognition from both the tech industry and policymakers.</p>
+
+
+
+<p>Sticking to the topic of the recent XZ Utils backdoor, to prevent incidents like that from recurring, policymakers and software vendors must take proactive steps to enhance the security and integrity of existing OSS projects. Many OSS maintainers work on these projects voluntarily, without compensation, and often in addition to their regular employment. This can lead to overwork and burnout, creating vulnerabilities that adversaries can exploit to compromise software. </p>
+
+
+
+<p>Without adequate safeguards and support systems, these maintainers operate in an environment that undervalues their crucial contributions and exposes them to significant risks. To address these challenges, there is a pressing need for policy interventions that recognise and financially support OSS development, along with industry-wide adoption of rigorous security practices. By implementing measures such as funding OSS projects, offering security training for maintainers, and developing comprehensive review processes, policymakers and vendors can protect maintainers from undue pressures and enhance the security of OSS.</p>
+
+
+
+<h3 class="wp-block-heading" id="h-the-programming-languages-that-power-the-economy">The Programming Languages That Power the Economy</h3>
+
+
+
+<p>Digging deeper, the study finds that the lion’s share of OSS value is actually generated by a few key programming languages, with Go, JavaScript, and Java leading the pack. These languages are not just popular among developers; they are instrumental in creating billions of dollars in value, further emphasizing the strategic importance of investing in and nurturing the OSS ecosystem.</p>
+
+
+
+<p>The notion of organisations opting to create proprietary programming languages rather than leveraging existing open-source options like JavaScript or Python libraries does not hold practical merit, considering the extensive resources and expertise required for such an endeavor. </p>
+
+
+
+<p>Constructing a new programming language from scratch involves not just the immense initial development effort but also the continuous maintenance, development of libraries, tools, and community support to make it viable for production use. Moreover, the existing ecosystems around popular languages such as JavaScript and Python are the result of years of collective effort and contributions from a global community, encompassing vast libraries and frameworks that facilitate rapid development and deployment of applications.</p>
+
+
+
+<p>These widely-used languages, however, are not without their vulnerabilities, including known <a href="https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=python">Common Vulnerabilities and Exposures</a> (CVEs) that pose significant security risks if left unpatched. Addressing these vulnerabilities often falls beyond the capacity of individual organisations, especially considering the breadth of open-source dependencies modern applications rely on. This scenario underscores the crucial role of large software vendors in enhancing the security infrastructure of the open-source ecosystem. </p>
+
+
+
+<p>By contributing to the security of these languages and libraries, either through direct code contributions, funding, or the provision of advanced security tools and services, these vendors can significantly reduce the potential attack surface for organisations worldwide. Such collaborative efforts between individual maintainers, organisations, and large vendors are essential in bolstering the overall security posture of the open-source software that underpins much of today’s digital infrastructure.</p>
+
+
+
+<h2 class="wp-block-heading" id="h-how-is-the-falco-project-staying-secure">How is the Falco project staying secure?</h2>
+
+
+
+<p>The Falco project emphasizes its commitment to maintaining vendor independence and the collective effort to bolster its security posture. A foundational pillar of Falco’s philosophy is its vendor-neutral stance, ensuring that the project benefits from a wide array of contributions without being tethered to any single company’s interests. This approach has fostered a diverse and robust community, with significant engineering resources dedicated by several leading companies.</p>
+
+
+
+<p>To prove the project’s maturity and reliability, Falco successfully graduated from the<a href="https://www.cncf.io/"> Cloud Native Computing Foundation</a> (CNCF) incubating status. This achievement was marked by a fairly rigorous <a href="https://docs.google.com/document/d/1Hkwp4qMoazqVhrODmJwDitvBI4chbsg0OBLQhRGmW3c/edit">Due Diligence process</a> conducted by the CNCF Technical Oversight Committee (TOC), including a comprehensive third-party security audit. This graduation not only proved Falco’s growth and sustainability, but also solidified Falco’s position as a leader in the open-source runtime security ecosystem.</p>
+
+
+
+<p><br>Reflecting on Falco’s commitment to an inclusive development environment, Falco boasts contributions from 17 organizations actively committing to the project. Notably, approximately 38% of contributions originated from diverse committers affiliated with renowned organizations such as Amazon, Cisco, Chainguard, Clastix, IBM, Microsoft, RedHat, SecureWorks, among others, alongside many individual contributors. This collective effort also demonstrates how Falco’s mission to foster a broad-based and resilient security tool is being enforced.</p>
+
+
+
+<p>Governance practices further cement Falco’s dedication to vendor neutrality, with specific measures to prevent any single entity from dominating the project’s direction. A key governance rule caps any organization’s eligible votes at 40%, ensuring balanced representation and decision-making within the project community.</p>
+
+
+
+<h2 class="wp-block-heading" id="h-towards-a-sustainable-future-for-oss">Towards a Sustainable Future for OSS</h2>
+
+
+
+<p>Harvard’s study revelations are a clear call to action to organisations to reflect on the value of OSS in their business, while also highlighting how many of those projects are taking appropriate steps to audit their projects. The paper further highlights the vital role of OSS in driving technological innovation and economic efficiency. </p>
+
+
+
+<p>However, this digital commons, much like its physical counterparts, is vulnerable to overuse and underinvestment – as seen with the XZ Utils backdoor. The findings advocate for a concerted effort to support OSS development, ensuring its sustainability and continued contribution to the global economy.<br><br>“<a href="https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4693148">The Value of Open Source Software</a>” study shines a spotlight on the hidden economic powerhouse that is OSS. By quantifying its value, the research not only celebrates the contributions of the OSS community but also highlights the critical need for strategic investment and support to secure its future. As we move forward in the digital era, the true value of OSS cannot be overstated—it is an indispensable resource that fuels innovation, drives efficiency, and shapes the technology landscape.</p>
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+
+
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+https://www.cncf.io/blog/2024/04/26/the-hidden-economy-of-open-source-software/https://www.cncf.io/blog/2024/04/26/the-hidden-economy-of-open-source-software/Thu, 25 Apr 2024 16:00:00 GMTOpen source software in AI and cloud trends to watch in 2024: thoughts from the Netris community<p><em>Member post originally published on <a href="https://www.netris.io/open-source-software-in-ai-and-cloud-trends-to-watch-in-2024/">Netris’s blog</a></em></p>
+
+
+
+<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="2500" height="1312" src="https://www.cncf.io/wp-content/uploads/2024/05/OpenSource-in-AI-banner.jpg" alt="Open Source Software in AI and Cloud Trends to Watch in 2024 banner" class="wp-image-106759" srcset="https://www.cncf.io/wp-content/uploads/2024/05/OpenSource-in-AI-banner.jpg 2500w, https://www.cncf.io/wp-content/uploads/2024/05/OpenSource-in-AI-banner-300x157.jpg 300w, https://www.cncf.io/wp-content/uploads/2024/05/OpenSource-in-AI-banner-1024x537.jpg 1024w, https://www.cncf.io/wp-content/uploads/2024/05/OpenSource-in-AI-banner-768x403.jpg 768w, https://www.cncf.io/wp-content/uploads/2024/05/OpenSource-in-AI-banner-194x102.jpg 194w, https://www.cncf.io/wp-content/uploads/2024/05/OpenSource-in-AI-banner-388x204.jpg 388w, https://www.cncf.io/wp-content/uploads/2024/05/OpenSource-in-AI-banner-776x408.jpg 776w, https://www.cncf.io/wp-content/uploads/2024/05/OpenSource-in-AI-banner-900x472.jpg 900w, https://www.cncf.io/wp-content/uploads/2024/05/OpenSource-in-AI-banner-1800x945.jpg 1800w, https://www.cncf.io/wp-content/uploads/2024/05/OpenSource-in-AI-banner-381x200.jpg 381w, https://www.cncf.io/wp-content/uploads/2024/05/OpenSource-in-AI-banner-762x400.jpg 762w, https://www.cncf.io/wp-content/uploads/2024/05/OpenSource-in-AI-banner-590x310.jpg 590w, https://www.cncf.io/wp-content/uploads/2024/05/OpenSource-in-AI-banner-1180x620.jpg 1180w" sizes="(max-width: 2500px) 100vw, 2500px" referrerpolicy="no-referrer"></figure>
+
+
+
+<p>Let’s face it: The world of open source software can feel boring – in a good way. Open source has become so pervasive, and so deeply entrenched within modern software stacks and ecosystems, that it’s easy not to think much about it. The era of AI, cloud and big data is here – and now, more than ever, open-source is playing a critical role.</p>
+
+
+
+<p>Yet the recent <a href="https://www.netris.io/recap-of-tech-trends-in-2023-and-predictions-for-2024-virtual-roundtable/">roundtable discussion</a> that Netris hosted with <strong>Kelsey Hightower</strong> was a reminder that there is still plenty of change afoot for open source software and everyone who uses it. The event didn’t aim to focus on open source specifically – and participants did discuss other important topics, like <a href="https://www.netris.io/the-2024-trends-on-cloud-computing-by-kelsey-hightower-and-alex-saroyan/">cloud computing trends</a> and the relationships between cloud competitors – but open source was a key part of the conversation.</p>
+
+
+
+<p>Specifically, Hightower and other participants discussed three themes that are poised to have major consequences for open source software in 2024 and beyond.</p>
+
+
+
+<h3 class="wp-block-heading">1. Open source licensing changes</h3>
+
+
+
+<p>Looking back at the past year, Hightower observed that the open source ecosystem had been rocked by some messy debates surrounding licensing – namely, HashiCorp’s decision to <a href="https://www.techtarget.com/searchitoperations/news/366555192/Terraform-Registry-TOS-change-stokes-open-source-ire">change the licensing terms</a> for future releases of some of its products (including Terraform, a popular Infrastructure-as-Code tool) and Red Hat’s new policy of placing source code for its Linux-based operating system behind what <a href="https://www.everand.com/article/661624560/The-Red-Hat-Paywall">critics deem a “paywall.”</a></p>
+
+
+
+<p>These developments affected only a handful of open source products, and neither turned previously open source solutions into closed source software. Nonetheless, they sparked a fair amount of controversy in the open source ecosystem about the <a href="https://thenewstack.io/closure-is-open-source-licensing-suddenly-unsustainable/">long-term viability of open source licenses</a>.</p>
+
+
+
+<p>Hightower’s take was that the license changes probably don’t signal a wholesale crisis for open source, but they do reflect a new reality that more and more companies will need to embrace if they want to continue to benefit open source: The need for a greater investment in open source projects by companies that can make meaningful contributions.</p>
+
+
+
+<p>“It’s not sustainable to work for free,” Hightower said. “Open source sustainability is coming to a head.”</p>
+
+
+
+<p>He added that “most people don’t know this but even Kubernetes struggled to get contributors,” referring to the open source container orchestration platform that he helped develop as a Distinguished Engineer at Google.</p>
+
+
+
+<p>The solution, in Hightower’s view, is simple: Companies that want to use open source software need to pay more developers to contribute to it. “If you want to avoid a Red Hat ‘paywall,’ go help write the code,” he said.</p>
+
+
+
+<h3 class="wp-block-heading">2. Open source, AI and network infrastructure</h3>
+
+
+
+<p>Roundtable participants also tackled what has become a buzzworthy topic over the past year: The role of open source software in the generative AI space.</p>
+
+
+
+<p>Alex Saroyan, Netris co-founder and CEO, noted that much of the discussion to date about open source and generative AI has centered on companies like Mistral, which aim to build open source generative AI models that can perform at least as well as those from vendors like OpenAI (which, despite its name, <a href="https://www.itprotoday.com/software-development/openai-not-open-source-neither-are-plenty-other-open-organizations">does not produce open source products</a>).</p>
+
+
+
+<p>That’s one important facet of open source in the realm of AI, Saroyan said. But another critical consideration – and one that hasn’t received nearly as much attention as it deserves – is the importance of providing open source AI projects with access to the cloud and networking infrastructure resources they need to train AI models.</p>
+
+
+
+<p>The reason why is simple: Few, if any, open source projects own the massive compute infrastructure they need to train models. Instead, they rely on cloud infrastructure for training. For AI model training, as well as inference, leveraging the Big 3 public cloud providers – meaning Amazon, Azure and Google Cloud Platform – becomes prohibitively expensive, especially at scale. To “do” AI, businesses need AWS alternatives, GCP alternatives and so on.</p>
+
+
+
+<p>“This is why we are seeing <strong>many new organizations launching AI cloud services for model training, as well as deploying private edge clouds for AI inference</strong>,” Saroyan said.</p>
+
+
+
+<p>Indeed, making AI infrastructure more accessible through alternative public and private cloud providers is “one of the reasons why we’re seeing new generations of ethernet technology, like NVIDIA Spectrum-X,” Saroyan noted.</p>
+
+
+
+<p>He added that “<strong>AI needs significantly more network and cloud infrastructure built in a highly-scalable but also highly cost-efficient manner.</strong> The new generation of networking solutions that Netris is helping customers to deliver depends on open source software and commodity hardware. DPUs are a big part of this picture,” he said, referring to special acceleration hardware known as Data Processings Units (DPUs) that are vital for scalable and efficient networks.</p>
+
+
+
+<p>In short: Open source has a critical role to play in the future of generative AI, and it’s not limited to open source AI models. Expect to see open source crop up in other corners of the <strong>AI ecosystem</strong> – including the networks that serve as the vital link between <strong>AI workloads and the infrastructure</strong> they depend on.</p>
+
+
+
+<h3 class="wp-block-heading">3. Shareable open source AI models</h3>
+
+
+
+<p>Hightower offered another prediction about how generative AI and open source will converge: “We’ll treat models like shareable libraries.”</p>
+
+
+
+<p>He meant that AI developers will use the open source example to build AI models that anyone can use and improve on. He envisions a world where borrowing someone else’s model is as simple as importing a module into your codebase or deploying a container from a public repository.</p>
+
+
+
+<p>Hightower added that shareable open source AI models will require an “ecosystem of companies” to build, share and maintain AI software. “No one private entity can run away with these things,” he said.</p>
+
+
+
+<p>Of course, given Hightower’s other observations during the roundtable about the importance for companies of backing open source products, any ecosystem that grows up surrounding open source models will need more than just volunteer labor. It will require committed investment from organizations with the means to support high-quality model development and training.</p>
+
+
+
+<h3 class="wp-block-heading">Conclusion: The future of open source</h3>
+
+
+
+<p>There’s plenty more to say about where open source is headed. But if Hightower and the rest of the Netris community are any guide – and we think they are! – expect new strategies for funding open source, as well as novel approaches to leveraging open source in the realm of AI, to become key open source trends during 2024.</p>
+
+
+
+<p>Expect, too, to stop thinking of open source as a “boring” type of resource that developers can take for granted.<strong> The open source world is changing</strong>, and while we don’t know exactly what’s coming next, we are confident that developments like open source licensing changes and the advent of <strong>generative AI will force open source projects and communities to adopt new strategies</strong>.</p>
+
+
+
+<p><a href="https://www.netris.io/open-source-software-in-ai-and-cloud-trends-to-watch-in-2024/#"></a></p>
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+
+
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+https://www.cncf.io/blog/2024/04/26/open-source-software-in-ai-and-cloud-trends-to-watch-in-2024-thoughts-from-the-netris-community/https://www.cncf.io/blog/2024/04/26/open-source-software-in-ai-and-cloud-trends-to-watch-in-2024-thoughts-from-the-netris-community/Thu, 25 Apr 2024 16:00:00 GMTHow Katalyst guarantees memory QoS for colocated applications<p><em>Member post originally published on <a href="https://gokatalyst.io/blog/2024/03/22/how-katalyst-guarantees-memory-qos-for-colocated-applications/">Katalyst’s blog</a></em></p>
+
+
+
+<p>In the previous post[1], we introduced Katalyst – a QoS-based resource management system that helps ByteDance improve resource efficiency through colocation of online and offline workloads. In the colocation scenario, memory management is a crucial topic. On the one hand, when memory is tight on nodes or containers, the performance of the application may be affected, leading to issues like latency jitter or OOM (Out of Memory) errors. In colocation scenarios, where memory is overcommitted, this problem can become more severe. On the other hand, there might be some memory on nodes that is less frequently used but not released, resulting in less available memory that can be allocated to offline jobs, thus hindering effective overcommitment. To address these issues, ByteDance has summarized its refined memory management strategies practiced during large-scale colocation into a user-space Kubernetes memory management solution called Memory Advisor, which has been open-sourced in the resource management system Katalyst. This article will focus on introducing the native memory management mechanisms of Kubernetes and the Linux kernel, their limitations, and how Katalyst, through Memory Advisor, improves memory utilization while ensuring the memory QoS for business applications.</p>
+
+
+
+<h2 class="wp-block-heading" id="limitations-of-native-memory-management">Limitations of native memory management</h2>
+
+
+
+<h3 class="wp-block-heading" id="memory-allocation-and-reclamation-of-linux-kernel">Memory allocation and reclamation of Linux kernel</h3>
+
+
+
+<p>Due to the much faster access speed of memory compared to accessing disk, Linux tends to adopt a greedy memory allocation strategy, aiming for maximum allocation. It only triggers reclamation when the memory watermark is relatively high. Memory allocation The Linux kernel has fast path and slow path for</p>
+
+
+
+<h4 class="wp-block-heading" id="memory-allocation">Memory allocation:</h4>
+
+
+
+<ol>
+<li>Fast path: It first attempts to do a fast path memory allocation and then assesses whether the overall free memory level will fall below the Low Watermark after allocation. If it does, a quick memory reclaim is performed before re-evaluating the possibility of allocation. If the condition is still not met, it enters the slow path.</li>
+
+
+
+<li>Slow path: In the slow path, it wakes up Kswapd to perform asynchronous memory reclaim and then attempts another round of fast memory allocation. If allocation fails, it tries memory compaction. If allocation is still unsuccessful, it attempts global direct memory reclaim, which involves scanning all zones and is time-consuming. If this also fails, it triggers a system-wide OOM event to release some memory and then retries fast memory allocation.</li>
+</ol>
+
+
+
+<h4 class="wp-block-heading" id="memory-reclamation">Memory reclamation</h4>
+
+
+
+<p>Memory reclamation can be categorized into two types based on the target: Memcg-based and Zone-based. The kernel’s native memory reclamation methods include the following:</p>
+
+
+
+<ol>
+<li>Memcg-level direct memory reclaim: If the Memory Usage of a cgroup reaches a threshold, it triggers synchronous memory reclamation at the memcg level to release some memory. If this is unsuccessful, it triggers a cgroup-level OOM event.</li>
+
+
+
+<li>Fast path memory reclaim: As mentioned earlier in the discussion of fast path memory allocation, fast memory reclamation is quick because it only requires reclaiming the number of pages needed for the current allocation.</li>
+</ol>
+
+
+
+<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1280" height="788" src="https://www.cncf.io/wp-content/uploads/2024/05/image-9.jpg" alt="Line chart showing available free pages to time on memory reclamation" class="wp-image-106752" title="Linux memory reclaim" srcset="https://www.cncf.io/wp-content/uploads/2024/05/image-9.jpg 1280w, https://www.cncf.io/wp-content/uploads/2024/05/image-9-300x185.jpg 300w, https://www.cncf.io/wp-content/uploads/2024/05/image-9-1024x630.jpg 1024w, https://www.cncf.io/wp-content/uploads/2024/05/image-9-768x473.jpg 768w, https://www.cncf.io/wp-content/uploads/2024/05/image-9-900x554.jpg 900w, https://www.cncf.io/wp-content/uploads/2024/05/image-9-325x200.jpg 325w, https://www.cncf.io/wp-content/uploads/2024/05/image-9-650x400.jpg 650w" sizes="(max-width: 1280px) 100vw, 1280px" referrerpolicy="no-referrer"></figure>
+
+
+
+<ol start="3">
+<li>Asynchronous memory reclaim: As shown in the diagram above, when the overall free memory of the system drops to the Low Watermark, Kswapd is awakened to asynchronously reclaim memory in the background until the High Watermark is reached.</li>
+
+
+
+<li>Direct memory reclaim: As depicted in the diagram above, if the overall free memory of the system drops to the Min Watermark, it triggers global direct memory reclaim. Since this process is synchronous and occurs in the context of process memory allocation, it has a significant impact on the performance of the system.</li>
+</ol>
+
+
+
+<h3 class="wp-block-heading" id="kubernetes-memory-management">Kubernetes Memory Management</h3>
+
+
+
+<h4 class="wp-block-heading" id="memory-limit">Memory limit</h4>
+
+
+
+<p>Kubelet sets the cgroup interface <code>memory.limit_in_bytes</code> based on the memory limits declared by each container within the pod, constraining the maximum memory usage for both the pod and its containers. When the memory usage of the pod or container reaches this limit, it triggers direct memory reclaim or even an OOM event.</p>
+
+
+
+<h4 class="wp-block-heading" id="eviction">Eviction</h4>
+
+
+
+<p>When the memory on a node becomes insufficient, K8s selects certain pods for eviction and marks the node with the taint <code>node.kubernetes.io/memory-pressure</code>, preventing additional pods from being scheduled on that node. The trigger condition for memory eviction is when the node’s working set reaches a threshold:</p>
+
+
+
+<pre class="wp-block-code"><code lang="sql" class="language-sql">memory.available := node.status.capacity[memory] - node.stats.memory.workingSet
+</code></pre>
+
+
+
+<p>Where <code>memory.available</code> is the threshold configured by the user. When sorting pods for eviction, the following criteria are considered:</p>
+
+
+
+<ol>
+<li>First, it checks if a pod’s memory usage exceeds its request; if so, it’s prioritized for eviction.</li>
+
+
+
+<li>Next, it compares the pods based on their priority, with lower-priority pods evicted first.</li>
+
+
+
+<li>Finally, it compares the difference between a pod’s memory usage and its request; pods with higher differences are evicted first.</li>
+</ol>
+
+
+
+<h4 class="wp-block-heading" id="oom">OOM</h4>
+
+
+
+<p>If direct memory reclaim still cannot meet the memory demands of processes on the node, it will trigger a system-wide OOM event. When the Kubelet starts a container, it configures <code>/proc/<pid>/oom_score_adj</code> based on the QoS level of the container’s associated pod and its memory request. This affects the order in which the container is selected for OOM Kill:</p>
+
+
+
+<ul>
+<li>For containers in critical pods or <code>Guaranteed</code> pods, their <code>oom_score_adj</code> is set to -997.</li>
+
+
+
+<li>For containers in <code>BestEffort</code> pods, their <code>oom_score_adj</code> is set to 1000.</li>
+
+
+
+<li>For containers in <code>Burstable</code> Pods, their <code>oom_score_adj</code> is calculated using the following formula: <code>min{max[1000 - (1000 * memoryRequest) / memoryCapacity, 1000 + guaranteedOOM]}</code></li>
+</ul>
+
+
+
+<h4 class="wp-block-heading" id="memory-qos">Memory QoS</h4>
+
+
+
+<p>Starting from version 1.22, K8s introduced the Memory QoS feature based on Cgroups v2 [2]. This feature ensures memory request guarantees for containers, thereby ensuring fairness in global memory reclaim among pods. The specific Cgroups configuration is as follows:</p>
+
+
+
+<ul>
+<li><code>memory.min</code>: Based on <code>requests.memory</code> configuration.</li>
+
+
+
+<li><code>memory.high</code>: Based on <code>limits.memory * throttlingfactor</code> (or <code>nodeallocatablememory * throttlingfactor</code>) configuration.</li>
+
+
+
+<li><code>memory.max</code>: Based on <code>limits.memory</code> (or <code>nodeallocatablememory</code>) configuration.</li>
+</ul>
+
+
+
+<p>In version 1.27 of K8s, enhancements were made to the Memory QoS feature to address the following issues:</p>
+
+
+
+<ol>
+<li>When container requests and limits are close, the throttle threshold configured in <code>memory.high</code> may not be effective due to <code>memory.high > memory.min</code> limitation.</li>
+
+
+
+<li>The calculated <code>memory.high</code> may be too low, resulting in frequent throttling and affecting application performance.</li>
+
+
+
+<li>The default value of <code>throttlingfactor</code> is too aggressive (0.8), causing frequent throttling for some Java applications that typically use more than 85% of memory.</li>
+</ol>
+
+
+
+<p>To address these issues, the following optimizations were made:</p>
+
+
+
+<ol>
+<li>Improvement in the calculation method of <code>memory.high</code>:</li>
+</ol>
+
+
+
+<pre class="wp-block-code"><code class="">memory.high = floor{[requests.memory + memory throttling factor(limits.memory or node allocatable memory - requests.memory)]/pageSize} * pageSize
+</code></pre>
+
+
+
+<ol start="2">
+<li>Adjustment of the default value of <code>throttlingfactor</code> to 0.9.</li>
+</ol>
+
+
+
+<h3 class="wp-block-heading" id="limitations">Limitations</h3>
+
+
+
+<p>From the introductions in the previous two sections, we can identify the following limitations in both K8s and the Linux kernel memory management mechanisms:</p>
+
+
+
+<ol>
+<li><strong>Lack of fairness mechanism in global memory reclamation:</strong> In scenarios where memory overcommitment occurs, even if the memory usage of all containers is significantly lower than the limit, the entire node’s memory may still reach the threshold for global memory reclaim. In the widely used Cgroups v1 environment, the memory request declared by containers is not reflected in Cgroups configuration by default, but serves only as a basis for scheduling. Therefore, there is a lack of fairness guarantee in global memory reclamation among pods, and available memory for containers is not divided proportionally based on requests, unlike CPU resources.</li>
+
+
+
+<li><strong>Lack of priority mechanism in global memory reclamation:</strong> In colocation scenarios, low-priority offline containers often run resource-intensive tasks and may request a large amount of memory. However, memory reclamation does not consider the priority of the applications, leading to high-priority online containers on nodes entering the slow path of direct memory reclaim, thereby disturbing the memory QoS of online applications.</li>
+
+
+
+<li><strong>Delayed triggering of native eviction mechanisms:</strong> K8s mainly ensures the priority and fairness of memory usage through kubelet-driven eviction. However, the triggering timing of native eviction mechanisms may occur after global memory reclamation, thus not taking effect promptly.</li>
+
+
+
+<li><strong>Impact on application performance by memcg-level direct memory reclaim:</strong> When the memory usage of a container reaches a threshold, memcg-level direct memory reclaim is triggered, causing latency in memory allocation, which may lead to business jitter.</li>
+</ol>
+
+
+
+<h2 class="wp-block-heading" id="katalyst-memory-advisor">Katalyst Memory Advisor</h2>
+
+
+
+<h3 class="wp-block-heading" id="overall-architecture">Overall architecture</h3>
+
+
+
+<p>The architecture of Katalyst Memory Advisor has undergone multiple discussions and iterations. It adopts a pluggable design, following a framework with plugins model, which enables developers to flexibly extend functionality and policies. The scopes of each component or module are as follows:</p>
+
+
+
+<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="723" height="891" src="https://www.cncf.io/wp-content/uploads/2024/05/image-9.png" alt="Architecture of Katalyst Memory Advisor" class="wp-image-106754" title="Architecture" srcset="https://www.cncf.io/wp-content/uploads/2024/05/image-9.png 723w, https://www.cncf.io/wp-content/uploads/2024/05/image-9-243x300.png 243w, https://www.cncf.io/wp-content/uploads/2024/05/image-9-162x200.png 162w, https://www.cncf.io/wp-content/uploads/2024/05/image-9-325x400.png 325w" sizes="(max-width: 723px) 100vw, 723px" referrerpolicy="no-referrer"></figure>
+
+
+
+<ul>
+<li><strong>Katalyst Agent:</strong> Resource management agent running on each node. The following modules are involved for memory QoS management:
+<ul>
+<li>Eviction Manager: A framework that extends the native eviction policies of the kubelet. It periodically invokes interfaces of eviction plugins, retrieves the results of eviction policy calculations, and executes eviction actions.</li>
+
+
+
+<li>Memory Eviction Plugins: Plugins for the Eviction Manager. The following plugins are involved for memory QoS management:
+<ul>
+<li>System Memory Pressure Plugin: Eviction strategy based on overall system-level memory pressure.</li>
+
+
+
+<li>NUMA Memory Pressure Plugin: Eviction strategy based on NUMA Node-level memory pressure.</li>
+
+
+
+<li>RSS Overuse Plugin: Eviction strategy based on Pod-level RSS overuse.</li>
+
+
+
+<li>Reclaimed Resource Pressure Plugin: Eviction strategy based on memory resource fulfillment of offline pods.</li>
+</ul>
+</li>
+
+
+
+<li>Memory QRM Plugin: Memory resource management plugin. For memory QoS management, it handles Memcg configuration for offline pods and implements the Drop Cache action.</li>
+
+
+
+<li>SysAdvisor: Algorithm module running on each node, supporting algorithm strategy extension through plugins. The following plugins are involved for memory QoS management:
+<ul>
+<li>Cache Reaper Plugin: Calculates the trigger timing for the Drop Cache action and identifies which pods need to have their cache dropped.</li>
+
+
+
+<li>Memory Guard Plugin: Calculates the real-time Memory Limit for offline pods.</li>
+
+
+
+<li>Memset Binder Plugin: Dynamically calculates which NUMA Node offline pods should be bound to.</li>
+</ul>
+</li>
+
+
+
+<li>Reporter: Out-of-band information reporting framework. For memory QoS management, it reports memory pressure-related Taints to Nodes or <code>CustomNodeResource</code> CRDs.</li>
+
+
+
+<li>MetaServer: Metadata management component of Katalyst Agent. For memory QoS management, it provides metadata for Pods and Containers, caches metrics, and offers dynamic configuration capabilities.</li>
+</ul>
+</li>
+
+
+
+<li><strong>Malachite:</strong> Metrics data collection component running on each node. For memory QoS management, it provides memory-related metrics at the Node, NUMA, and Container levels.</li>
+
+
+
+<li><strong>Katalyst Scheduler:</strong> The following plugins are involved for memory QoS management:
+<ul>
+<li>Native <code>TaintToleration</code> Plugin: Filters based on Node Taints.</li>
+
+
+
+<li>Extended <code>QoSAwareTaintToleration</code> Plugin: Implements scheduling prohibitions based on Taints defined in <code>CustomNodeResource</code> CRDs for QoS awareness.</li>
+</ul>
+</li>
+</ul>
+
+
+
+<h3 class="wp-block-heading" id="detailed-design">Detailed design</h3>
+
+
+
+<h4 class="wp-block-heading" id="multi-dimensional-interference-detection">Multi-dimensional interference detection</h4>
+
+
+
+<p>Memory Advisor performs periodic interference detection to proactively sense memory pressure and trigger corresponding mitigation measures. Currently, the following dimensions of interference detection are supported:</p>
+
+
+
+<ol>
+<li>System and NUMA-level memory watermark: Comparing the free memory watermark at the system and NUMA levels with the threshold watermark of global asynchronous memory reclamation (Low Watermark), to avoid triggering global direct memory reclaim as much as possible.</li>
+
+
+
+<li>Kswapd memory reclamation rate at the system level: If the rate of global asynchronous memory reclamation is high and continues for an extended period, it indicates significant memory pressure on the system, which may likely trigger global direct memory reclaim in the future.</li>
+
+
+
+<li>Pod-level RSS overuse: Overcommitment can fully utilize a node’s memory, but it cannot control whether the overcommitted memory is used for page cache or RSS. If the RSS usage of certain pods far exceeds their request, it may result in a high node memory watermark that cannot be reclaimed. This can affect other pods’ inability to use sufficient page cache, leading to performance degradation, or it may result in an OOM event.</li>
+
+
+
+<li>QoS-level memory resource fulfillment: By comparing the supply of reclaimed memory on the node with the total memory request of <code>reclaimed_cores</code> QoS level on that node, it calculates the memory resource fulfillment of offline jobs to prevent severe impacts on the service quality of offline jobs.</li>
+</ol>
+
+
+
+<h4 class="wp-block-heading" id="multi-tiered-mitigation-measures">Multi-tiered mitigation measures</h4>
+
+
+
+<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1080" height="431" src="https://www.cncf.io/wp-content/uploads/2024/05/image-10.png" alt="Diagram flow showing Multi-tiered mitigation measures" class="wp-image-106755" title="Mitigations" srcset="https://www.cncf.io/wp-content/uploads/2024/05/image-10.png 1080w, https://www.cncf.io/wp-content/uploads/2024/05/image-10-300x120.png 300w, https://www.cncf.io/wp-content/uploads/2024/05/image-10-1024x409.png 1024w, https://www.cncf.io/wp-content/uploads/2024/05/image-10-768x306.png 768w, https://www.cncf.io/wp-content/uploads/2024/05/image-10-900x359.png 900w, https://www.cncf.io/wp-content/uploads/2024/05/image-10-501x200.png 501w, https://www.cncf.io/wp-content/uploads/2024/05/image-10-1002x400.png 1002w" sizes="(max-width: 1080px) 100vw, 1080px" referrerpolicy="no-referrer"></figure>
+
+
+
+<p>Based on the different levels of abnormality feedback from interference detection, Memory Advisor supports multi-tiered mitigation measures. While avoiding interference with high-priority pods, it aims to minimize the impact on victim pods.</p>
+
+
+
+<h5 class="wp-block-heading" id="forbid-scheduling">Forbid Scheduling</h5>
+
+
+
+<p>Forbidding scheduling is the least impactful mitigation measure. When any level of system abnormality is detected by interference detection, scheduling is forbidden on the node to prevent further scheduling of pods, thus preventing the situation from worsening. Currently, Memory Advisor supports this feature for all pods through Node Taint. In the future, we will enable the scheduler to be aware of taints extended in <code>CustomNodeResource</code> CRDs to achieve fine-grained scheduling prohibition for <code>reclaimed_cores</code> pods.</p>
+
+
+
+<h5 class="wp-block-heading" id="tune-memcg">Tune Memcg</h5>
+
+
+
+<p>Tune Memcg is a mitigation measure with a relatively minor impact on victim pods. When the degree of abnormality detected by interference detection is low, Tune Memcg operations are triggered. This selects some <code>reclaimed_cores</code> pods and configures them with higher memory reclamation trigger thresholds to trigger memory reclamation earlier, thereby avoiding triggering global direct memory reclaim as much as possible. Tune Memcg is not enabled by default because it requires the use of veLinux kernel’s open-source Memcg asynchronous memory reclamation feature[3], which does not affect usage.</p>
+
+
+
+<h5 class="wp-block-heading" id="drop-cache">Drop Cache</h5>
+
+
+
+<p>Drop Cache is a mitigation measure with a moderate impact on victim pods. When the degree of abnormality detected by interference detection is moderate, drop cache operations are triggered. This selects some <code>reclaimed_cores</code> pods with high cache usage and forcefully releases their cache to avoid triggering global direct memory reclaim as much as possible. In Cgroups v1 environments, cache release is triggered through the <code>memory.force_empty</code> interface:</p>
+
+
+
+<pre class="wp-block-code"><code class="">echo 0 > memory.force_empty
+</code></pre>
+
+
+
+<p>In Cgroups v2 environments, cache release is triggered by writing a large value to the <code>memory.reclaim</code> interface, such as:</p>
+
+
+
+<pre class="wp-block-code"><code class="">echo 100G > memory.reclaim
+</code></pre>
+
+
+
+<p>As drop cache is a time-consuming operation, we have implemented an asynchronous task execution framework to avoid blocking the main process. Technical details of this part will be discussed in future articles.</p>
+
+
+
+<h5 class="wp-block-heading" id="eviction-1">Eviction</h5>
+
+
+
+<p>Eviction is a measure with a significant impact on victim pods, but it is the fastest and most effective fallback measure. When a high degree of abnormality is detected by interference detection, eviction at the system or NUMA level (or only for <code>reclaimed_cores</code> pods) is triggered to effectively avoid triggering global direct memory reclaim. Memory Advisor supports users to configure custom sorting logic for pods to be evicted. If users have not configured it, the default sorting logic is as follows:</p>
+
+
+
+<ol>
+<li>Sort pods based on their QoS level, with <code>reclaimed_cores</code> > <code>shared_cores</code> / <code>dedicated_cores</code>.</li>
+
+
+
+<li>Sort pods based on their priority, with lower priority pods evicted first.</li>
+
+
+
+<li>Sort pods based on their memory usage, with higher usage pods evicted first. We have abstracted an eviction manager framework in Katalyst agent. This framework delegates eviction policies to plugins and consolidates eviction actions in the manager, offering the following advantages:</li>
+</ol>
+
+
+
+<ul>
+<li>Plugins and managers can communicate through local function calls or gRPC, allowing flexible plugin start and stop.</li>
+
+
+
+<li>The manager can easily support governance operations such as filtering, rate limiting, sorting, and auditing for eviction.</li>
+
+
+
+<li>Support for dry run on plugins in the manager, allowing thorough validation of strategies before they take effect.</li>
+</ul>
+
+
+
+<h4 class="wp-block-heading" id="resource-cap-for-reclaimed_cores">Resource cap for reclaimed_cores</h4>
+
+
+
+<p>To prevent offline containers from excessively using memory and affecting the service quality of online containers, we limit the total memory usage of <code>reclaimed_cores</code> pods through a resource cap. Specifically, we have expanded a memory guard plugin in SysAdvisor. This plugin periodically calculates the total amount of memory that <code>reclaimed_cores</code> pods can use as a whole and accordingly write <code>memory.limit_in_bytes</code> file of the <code>BestEffort</code> cgroup through the memory QRM plugin.</p>
+
+
+
+<h4 class="wp-block-heading" id="memory-migration">Memory migration</h4>
+
+
+
+<p>For applications like Flink, the performance of services is strongly correlated with memory bandwidth and memory latency, and they also consume a significant amount of memory. The default memory allocation strategy prioritizes memory allocation from the local NUMA node to achieve lower memory access latency. However, on the other hand, the default memory allocation strategy may lead to uneven memory usage across NUMA nodes, causing certain NUMA nodes to become hotspots under excessive pressure, which severely impacts service performance and leads to latency issues. Therefore, we use Memory Advisor to monitor the memory watermark of each NUMA node and dynamically adjust the NUMA node bindings of containers for memory migration to prevent any NUMA node from becoming a hotspot. During the implementation of the memory dynamic migration feature in production environments, we encountered exceptional situations that could lead to system hang-ups. As a result, we optimized the method of memory migration. This practical experience will be elaborated on in subsequent blogs.</p>
+
+
+
+<h4 class="wp-block-heading" id="differentiated-memcg-level-reclamation-strategy">Differentiated memcg-level reclamation strategy</h4>
+
+
+
+<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1080" height="525" src="https://www.cncf.io/wp-content/uploads/2024/05/image-11.jpg" alt="Line chart showing per memcg free pages to time on memory reclamation strategy" class="wp-image-106756" title="Memcg Memory Reclaim" srcset="https://www.cncf.io/wp-content/uploads/2024/05/image-11.jpg 1080w, https://www.cncf.io/wp-content/uploads/2024/05/image-11-300x146.jpg 300w, https://www.cncf.io/wp-content/uploads/2024/05/image-11-1024x498.jpg 1024w, https://www.cncf.io/wp-content/uploads/2024/05/image-11-768x373.jpg 768w, https://www.cncf.io/wp-content/uploads/2024/05/image-11-900x438.jpg 900w, https://www.cncf.io/wp-content/uploads/2024/05/image-11-411x200.jpg 411w, https://www.cncf.io/wp-content/uploads/2024/05/image-11-823x400.jpg 823w" sizes="(max-width: 1080px) 100vw, 1080px" referrerpolicy="no-referrer"></figure>
+
+
+
+<p>Given that memcg-level direct memory reclaim can significantly impact application performance, the kernel team at ByteDance has enhanced the Linux kernel (i.e. veLinux) with memcg-level asynchronous memory reclamation features, which have been open-sourced [4]. In colocation scenarios, the typical I/O activities of online applications involve reading and writing logs, whereas those of offline tasks involve more frequent file I/O operations, with page cache having a significant impact on the performance of offline jobs. Therefore, through Memory Advisor, we support differentiated memory reclamation strategies at the memcg level:</p>
+
+
+
+<ul>
+<li>For applications requiring a large amount of page cache (such as offline jobs), users can specify a relatively lower memcg-level asynchronous memory reclamation threshold through pod annotations. This conservative memory reclamation approach allows for more page cache usage.</li>
+
+
+
+<li>Conversely, for applications requiring minimized performance degradation due to direct memory reclaim, users can configure a relatively aggressive memcg-level asynchronous reclamation strategy through pod annotations. This feature is not enabled by default as it requires patches from the veLinux kernel.</li>
+</ul>
+
+
+
+<h2 class="wp-block-heading" id="future-plans">Future plans</h2>
+
+
+
+<p>In subsequent versions of Katalyst, we will continue to iterate on Memory Advisor to enhance its support for a wider range of user scenarios.</p>
+
+
+
+<h3 class="wp-block-heading" id="decoupling-some-capabilities-from-qos">Decoupling some capabilities from QoS</h3>
+
+
+
+<p>Memory Advisor has extended some enhanced memory management capabilities in colocation scenarios, where some of these capabilities are orthogonal to QoS and remain applicable even in non-colocation scenarios. Therefore, in subsequent iterations, we will decouple features such as memcg-level differentiated reclamation strategy, interference detection, and mitigation from QoS enhancement. This will turn them into finely-grained memory management capabilities applicable to general scenarios, enabling users in non-colocation scenarios to utilize them as well.</p>
+
+
+
+<h3 class="wp-block-heading" id="oom-priority">OOM priority</h3>
+
+
+
+<p>In the context mentioned earlier, Kubernetes configures different <code>oom_score_adj</code> values for containers based on pod’s QoS level. However, the final OOM Score can still be influenced by other factors such as memory usage. In tidal colocation [5] scenarios, where offline pods belong to the same QoS level, there may be no guarantee that offline pods will be OOM-killed before online pods. Therefore, there is a need to introduce a Katalyst QoS enhancement: QoS priority. Memory Advisor should be able to configure corresponding <code>oom_score_adj</code> values for containers belonging to different QoS priority levels in user space, ensuring strict OOM sequence for offline pods. Additionally, the ByteDance kernel team recently submitted a patch to the Linux kernel [6], aiming to programmatically customize the kernel’s OOM behavior through BPF hooks. This initiative seeks to enhance flexibility in defining OOM strategies.</p>
+
+
+
+<h3 class="wp-block-heading" id="cold-memory-offloading">Cold memory offloading</h3>
+
+
+
+<p>There may be some less frequently used memory (referred to as cold memory) on the node that has not been released, leading to a limited amount of memory available for offline job usage. This situation prevents effective memory overcommitment, as the memory that could be allocated to offline jobs remains underutilized.</p>
+
+
+
+<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1080" height="402" src="https://www.cncf.io/wp-content/uploads/2024/05/image-11-1.jpg" alt="Diagram flow showing cold memory offloading achitecture" class="wp-image-106757" title="Cold Memory Offloading" srcset="https://www.cncf.io/wp-content/uploads/2024/05/image-11-1.jpg 1080w, https://www.cncf.io/wp-content/uploads/2024/05/image-11-1-300x112.jpg 300w, https://www.cncf.io/wp-content/uploads/2024/05/image-11-1-1024x381.jpg 1024w, https://www.cncf.io/wp-content/uploads/2024/05/image-11-1-768x286.jpg 768w, https://www.cncf.io/wp-content/uploads/2024/05/image-11-1-900x335.jpg 900w, https://www.cncf.io/wp-content/uploads/2024/05/image-11-1-537x200.jpg 537w, https://www.cncf.io/wp-content/uploads/2024/05/image-11-1-1075x400.jpg 1075w" sizes="(max-width: 1080px) 100vw, 1080px" referrerpolicy="no-referrer"></figure>
+
+
+
+<p>To increase the amount of memory available for allocation, we have referenced Meta’s Transparent Memory Offloading (TMO) paper [7]. In the future, Memory Advisor will utilize the procfs-based memory pressure monitoring framework (PSI) in user space to detect memory pressure. When memory pressure is low, memory reclamation will be triggered proactively. Additionally, we will leverage the DAMON sub-module for memory hotness detection to gather information on memory usage patterns. This information will be used to offload cold memory to relatively inexpensive storage devices or compress it using zRAM, thereby saving memory space and improving memory resource utilization. The technical details of this feature will be elaborated on in subsequent blogs.</p>
+
+
+
+<h2 class="wp-block-heading" id="summary">Summary</h2>
+
+
+
+<p>At ByteDance, Katalyst is deployed across over 900,000 nodes, managing tens of millions of cores and unifying the management of various workload types, including microservices, search, advertising, storage, big data, and AI jobs. Katalyst has improved daily resource utilization at ByteDance from 20% to 60%, while ensuring that the QoS requirement of various workload types is satisfied at the same time. In the future, Katalyst Memory Advisor will continue to iterate and optimize. Further technical insights into features such as cold memory offloading and memory migration optimizations will be explained in subsequent blogs. Stay tuned!</p>
+
+
+
+<h2 class="wp-block-heading" id="references">References</h2>
+
+
+
+<ul>
+<li>[1] A brief introduction to Katalyst: <a href="https://www.cncf.io/blog/2023/12/26/katalyst-a-qos-based-resource-management-system-for-workload-colocation-on-kubernetes/">https://www.cncf.io/blog/2023/12/26/katalyst-a-qos-based-resource-management-system-for-workload-colocation-on-kubernetes/</a></li>
+
+
+
+<li>[2] Kubernetes eviction strategy: <a href="https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/">https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/</a></li>
+
+
+
+<li>[3] Memory QoS KEP: <a href="https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2570-memory-qos">https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2570-memory-qos</a></li>
+
+
+
+<li>[4] Memcg-level async reclaim:<a href="https://github.com/bytedance/kernel/commit/7d7386ec89caf078f21836c5cae33ffa886125c4">https://github.com/bytedance/kernel/commit/7d7386ec89caf078f21836c5cae33ffa886125c4</a></li>
+
+
+
+<li>[5] Tidal colocation: <a href="https://gokatalyst.io/docs/user-guide/tidal-colocation/">https://gokatalyst.io/docs/user-guide/tidal-colocation/</a></li>
+
+
+
+<li>[6] BPF hook for selecting victim task during OOM events: <a href="https://lore.kernel.org/lkml/20230804093804.47039-1-zhouchuyi@bytedance.com/">https://lore.kernel.org/lkml/20230804093804.47039-1-zhouchuyi@bytedance.com/</a></li>
+
+
+
+<li>[7] TMO paper:<a href="https://www.pdl.cmu.edu/ftp/NVM/tmo_asplos22.pdf">https://www.pdl.cmu.edu/ftp/NVM/tmo_asplos22.pdf</a></li>
+</ul>
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+
+
+
+<div style="height:80px" aria-hidden="true" class="wp-block-spacer is-style-80-120">
+</div>
+https://www.cncf.io/blog/2024/04/25/how-katalyst-guarantees-memory-qos-for-colocated-applications/https://www.cncf.io/blog/2024/04/25/how-katalyst-guarantees-memory-qos-for-colocated-applications/Wed, 24 Apr 2024 16:00:00 GMT
\ No newline at end of file
diff --git a/main.py b/main.py
index 2c4be01..3b234cd 100644
--- a/main.py
+++ b/main.py
@@ -20,7 +20,7 @@ def main():
article_list = xml_dict_to_article_list(
xml_dict, ["rss", "channel", "item"], ["title", "description"]
)
- for i in range(0, range(0, len(article_list.list))):
+ for i in range(0, len(article_list.list)):
article_list.list[i].replace_keywords(
wrapper.content_to_5_keywords(article_list.list[i].get_content(), "ZH")
)
diff --git a/test.csv b/test.csv
new file mode 100644
index 0000000..89069be
--- /dev/null
+++ b/test.csv
@@ -0,0 +1,5042 @@
+learn,more,43
+make,decision,34
+have,impact,23
+manage,application,21
+take,action,21
+train,model,21
+trigger,reclaim,21
+solve,problem,20
+do,what,19
+play,role,18
+split,resource,18
+do,this,18
+provide,insight,18
+reduce,cost,16
+address,challenge,16
+enter,process,15
+use,that,14
+address,issue,14
+reduce,time,14
+harness,power,13
+take,step,13
+use,service,13
+analyze,data,13
+adopt,strategy,13
+store,data,13
+meet,requirement,13
+move,data,13
+use,color,12
+use,cloud,12
+have,workload,12
+trigger,reclamation,12
+empower,defender,12
+offer,insight,11
+ask,question,11
+build,platform,11
+answer,question,11
+eliminate,need,11
+have,access,10
+enable,user,10
+impact,performance,10
+trigger,event,10
+protect,data,10
+receive,callback,10
+make,change,10
+imply,endorsement,10
+create,theme,9
+have,problem,9
+adopt,approach,9
+start,pod,9
+modify,resource,9
+reach,consensus,9
+reach,number,9
+expose,gpus,9
+support,strategy,9
+use,plugin,9
+deploy,model,9
+address,this,9
+affect,performance,9
+empower,team,9
+support,development,9
+build,model,9
+improve,utilization,9
+reach,threshold,9
+select,pod,9
+involve,plugins,9
+use,model,9
+take,advantage,9
+use,command,8
+gather,information,8
+take,look,8
+enable,developer,8
+have,cluster,8
+provide,view,8
+improve,efficiency,8
+minimize,impact,8
+use,table,8
+provide,access,8
+create,function,8
+have,system,8
+spend,time,8
+create,replica,8
+process,payment,8
+invoke,workflow,8
+improve,experience,8
+mitigate,risk,7
+build,pipeline,7
+monitor,health,7
+manage,gpus,7
+have,requirement,7
+enhance,efficiency,7
+trigger,alert,7
+calculate,cost,7
+enhance,security,7
+create,language,7
+write,code,7
+release,memory,7
+take,effect,7
+create,table,7
+reduce,risk,7
+get,data,7
+have,data,7
+call,function,7
+use,metric,7
+increase,throughput,7
+clone,project,6
+add,color,6
+give,talk,6
+thank,you,6
+differenciate,thing,6
+add,theme,6
+use,any,6
+use,variable,6
+get,pod,6
+use,theme,6
+get,bash,6
+update,theme,6
+witness,traction,6
+enhance,flexibility,6
+provide,control,6
+push,boundary,6
+use,deployment,6
+choose,multi,6
+choose,deployment,6
+adopt,deployment,6
+reflect,maturity,6
+provide,identity,6
+introduce,workload,6
+discuss,detail,6
+make,attempt,6
+send,them,6
+monitor,creation,6
+deploy,cluster,6
+perform,add,6
+call,client,6
+repeat,process,6
+show,process,6
+receive,notification,6
+scale,cluster,6
+update,cluster,6
+implement,which,6
+accelerate,workload,6
+utilize,gpu,6
+support,sharing,6
+use,gpus,6
+measure,cost,6
+find,balance,6
+build,control,6
+implement,solution,6
+encounter,challenge,6
+gain,clarity,6
+identify,inefficiency,6
+underscore,importance,6
+enable,you,6
+set,budget,6
+manage,infrastructure,6
+take,that,6
+drive,innovation,6
+leverage,source,6
+boast,contribution,6
+bolster,posture,6
+allocate,that,6
+perform,reclaim,6
+enter,path,6
+exceed,request,6
+use,memory,6
+use,cache,6
+trigger,operation,6
+trigger,release,6
+extend,capability,6
+configure,value,6
+use,function,6
+achieve,this,6
+create,dataset,6
+set,value,6
+use,framework,6
+view,recommendation,6
+do,that,6
+enable,customer,6
+take,minute,6
+provide,you,6
+use,language,6
+create,rule,6
+simplify,process,6
+scale,database,6
+introduce,complexity,6
+write,data,6
+design,system,6
+send,request,6
+use,terraform,6
+streamline,process,6
+create,schema,6
+null,key,6
+use,algorithm,6
+offer,service,6
+accelerate,journey,6
+measure,impact,6
+enable,delete,6
+update,bucket,6
+disable,delete,6
+pose,challenge,6
+accomplish,goal,6
+meet,threshold,5
+perform,analysis,5
+automate,step,5
+implement,version,5
+add,cluster,5
+give,priority,5
+simplify,management,5
+provide,information,5
+provision,node,5
+use,image,5
+set,limit,5
+give,access,5
+estimate,cost,5
+set,environment,5
+give,tool,5
+use,compute,5
+face,challenge,5
+identify,resource,5
+address,need,5
+implement,feature,5
+drive,efficiency,5
+have,consequence,5
+receive,attention,5
+have,role,5
+introduce,feature,5
+provide,metadata,5
+create,system,5
+build,application,5
+make,improvement,5
+provide,mechanism,5
+meet,need,5
+scale,workload,5
+build,system,5
+use,replication,5
+include,feature,5
+provide,example,5
+have,step,5
+make,request,5
+create,prompt,5
+access,data,5
+take,hour,5
+deliver,experience,5
+develop,system,5
+exceed,threshold,5
+complete,trip,5
+use,case,5
+present,challenge,5
+mitigate,this,5
+have,value,5
+ingest,data,5
+run,workload,4
+have,chance,4
+take,care,4
+have,theme,4
+see,what,4
+show,difference,4
+put,lot,4
+reduce,dependency,4
+leverage,infrastructure,4
+reduce,latency,4
+lack,support,4
+pose,problem,4
+use,operator,4
+create,that,4
+allocate,workload,4
+share,resource,4
+provide,integration,4
+manage,cost,4
+provide,mapping,4
+provide,infrastructure,4
+scale,service,4
+offer,solution,4
+address,problem,4
+drive,cost,4
+inform,owner,4
+normalize,metric,4
+apply,rule,4
+have,service,4
+get,alert,4
+require,response,4
+have,resource,4
+track,usage,4
+pose,risk,4
+know,this,4
+meet,demand,4
+use,formula,4
+offer,capability,4
+prevent,impact,4
+implement,framework,4
+consume,amount,4
+use,data,4
+combine,type,4
+generate,image,4
+integrate,data,4
+maintain,integrity,4
+streamline,integration,4
+overcome,challenge,4
+centralize,data,4
+enable,access,4
+open,world,4
+describe,image,4
+create,caption,4
+deploy,function,4
+enable,api,4
+enable,apis,4
+grant,access,4
+start,you,4
+improve,security,4
+view,all,4
+have,permission,4
+manage,operation,4
+include,recommendation,4
+receive,recommendation,4
+provide,recommendation,4
+take,car,4
+get,value,4
+modernize,market,4
+access,service,4
+take,month,4
+configure,reservation,4
+end,user,4
+replicate,data,4
+manage,recovery,4
+provide,level,4
+take,time,4
+create,reservation,4
+specify,location,4
+analyze,code,4
+identify,killswitch,4
+provide,tool,4
+secure,use,4
+recommend,step,4
+create,detection,4
+simplify,task,4
+keep,people,4
+drive,productivity,4
+turn,intelligence,4
+build,playbook,4
+incorporate,practice,4
+parse,file,4
+reduce,maintenance,4
+help,you,4
+operationalize,intelligence,4
+protect,organization,4
+include,policy,4
+use,signal,4
+power,service,4
+scale,traffic,4
+require,downtime,4
+impact,availability,4
+reduce,load,4
+require,understanding,4
+handle,traffic,4
+invoke,function,4
+use,callback,4
+use,workflow,4
+lose,response,4
+solve,this,4
+pass,collectionid,4
+raise,exception,4
+add,retries,4
+receive,request,4
+retry,callback,4
+require,space,4
+enable,sync,4
+sync,resource,4
+set,scope,4
+manage,resource,4
+target,namespaces,4
+delegate,management,4
+use,sync,4
+use,repository,4
+leverage,integration,4
+use,bigquery,4
+create,diagram,4
+use,tool,4
+create,ddls,4
+write,prompt,4
+create,key,4
+have,image,4
+call,model,4
+check,tutorial,4
+load,data,4
+fetch,data,4
+fetch,object,4
+access,api,4
+access,prediction,4
+provide,data,4
+run,application,4
+view,session,4
+provide,constituent,4
+need,proximity,4
+define,which,4
+solve,challenge,4
+develop,model,4
+use,delete,4
+assess,impact,4
+use,explorer,4
+generate,list,4
+update,policy,4
+set,project,4
+set,delete,4
+use,layer,4
+create,bucket,4
+obtain,list,4
+use,which,4
+ensure,quality,4
+test,flow,4
+request,trip,4
+migrate,data,4
+give,confidence,4
+find,issue,4
+build,index,4
+scale,infrastructure,4
+balance,data,4
+increase,number,4
+increase,utilization,4
+select,peer,4
+improve,reliability,4
+improve,latency,4
+set,timeout,4
+complete,challenge,4
+send,hold,4
+change,course,3
+set,star,3
+establish,baseline,3
+operate,application,3
+celebrate,decade,3
+blend,element,3
+celebrate,figure,3
+celebrate,preview,3
+celebrate,people,3
+shape,kubernetes,3
+have,you,3
+limit,space,3
+limit,rsvp,3
+join,party,3
+have,livestream,3
+join,celebration,3
+request,party,3
+organize,event,3
+include,quebec,3
+include,cloud,3
+join,one,3
+join,gathering,3
+continue,celebration,3
+reformats,output,3
+read,output,3
+understand,that,3
+want,pitch,3
+cusotmize,theme,3
+apply,patch,3
+change,color,3
+think,colory,3
+support,scheme,3
+use,set,3
+change,theme,3
+adapt,color,3
+colorize,field,3
+have,sort,3
+check,page,3
+mentionned,blindness,3
+belived,what,3
+rate,any,3
+put,light,3
+get,functionnality,3
+use,green,3
+have,answer,3
+learn,thing,3
+add,text,3
+explain,status,3
+process,kind,3
+configure,color,3
+use,name,3
+define,whatever,3
+change,anything,3
+use,way,3
+define,color,3
+use,part,3
+change,background,3
+use,visibility,3
+customize,output,3
+create,file,3
+embed,theme,3
+check,content,3
+build,theme,3
+use,easiest,3
+check,doc,3
+pick,theme,3
+update,some,3
+change,pod,3
+change,yaml,3
+use,file,3
+add,content,3
+take,variable,3
+nest,part,3
+remove,part,3
+show,pod,3
+have,impairement,3
+base,work,3
+provide,out,3
+help,people,3
+take,responsability,3
+find,website,3
+load,image,3
+use,view,3
+upload,one,3
+capture,command,3
+view,view,3
+understand,issue,3
+lose,most,3
+test,progression,3
+identify,palette,3
+perceive,that,3
+achieve,theme,3
+differenciate,content,3
+need,what,3
+have,hue,3
+show,situation,3
+use,website,3
+use,schema,3
+cut,rainbow,3
+use,bold,3
+invert,error,3
+concern,you,3
+set,variable,3
+set,file,3
+open,issue,3
+enhenced,theme,3
+modify,one,3
+add,customization,3
+leave,feedback,3
+mention,condition,3
+suite,each,3
+encourage,you,3
+set,theme,3
+see,screen,3
+make,fun,3
+suffer,sort,3
+explain,them,3
+use,kubectl,3
+check,kubecolor,3
+help,person,3
+have,game,3
+experience,feeling,3
+gather,survey,3
+craft,guide,3
+expect,that,3
+foresee,growth,3
+demand,data,3
+construct,infrastructure,3
+offer,model,3
+enable,enterprise,3
+implement,functionality,3
+incorporate,service,3
+enable,portability,3
+offer,approach,3
+manage,complexity,3
+integrate,environment,3
+gain,scalability,3
+optimize,allocation,3
+strengthen,capability,3
+foster,agility,3
+evolve,requirement,3
+bolster,security,3
+employ,professional,3
+ensure,protection,3
+expect,landscape,3
+establish,environment,3
+enable,analysis,3
+expect,deployment,3
+bolster,viability,3
+evolve,need,3
+expect,computing,3
+experience,growth,3
+fuel,trend,3
+encompass,practice,3
+mitigate,impact,3
+decrease,emission,3
+involve,selection,3
+minimize,waste,3
+promote,sustainability,3
+see,expansion,3
+bring,method,3
+eradicate,necessity,3
+empower,user,3
+deploy,code,3
+offer,benefit,3
+decrease,cost,3
+keep,pace,3
+distil,trend,3
+reshape,approach,3
+embrace,them,3
+propel,organization,3
+navigate,trend,3
+package,campaign,3
+drive,campaign,3
+pull,customer,3
+apply,omnichannel,3
+cover,expanse,3
+experience,attack,3
+exploit,type,3
+include,damage,3
+cost,organization,3
+cost,average,3
+increase,spending,3
+create,series,3
+divide,framework,3
+verify,code,3
+require,commits,3
+use,hook,3
+commit,secret,3
+define,level,3
+commit,code,3
+include,vulnerability,3
+verify,material,3
+scan,dependency,3
+download,they,3
+protect,pipeline,3
+maintain,build,3
+protect,artefact,3
+distribute,metadata,3
+verify,that,3
+join,register,3
+embrace,multi,3
+embrace,clustering,3
+embrace,management,3
+outperform,cluster,3
+have,pod,3
+hold,node,3
+use,karmada,3
+set,group,3
+promote,support,3
+propose,pet,3
+need,name,3
+replace,one,3
+introduce,statefulset,3
+manage,pod,3
+constitute,state,3
+have,order,3
+affect,scale,3
+involve,determination,3
+affect,correctness,3
+have,identifier,3
+incorporate,id,3
+use,submariner,3
+bridge,communication,3
+solve,function,3
+provide,policy,3
+realize,function,3
+update,xline,3
+deploy,operator,3
+complete,operation,3
+create,node,3
+perform,member,3
+update,topology,3
+start,node,3
+perform,operation,3
+affect,process,3
+bypass,problem,3
+adopt,method,3
+define,resource,3
+describe,topology,3
+apply,resource,3
+contain,number,3
+generate,name,3
+use,topology,3
+bypass,lack,3
+involve,change,3
+have,offs,3
+compare,characteristic,3
+create,cluster,3
+configure,network,3
+add,record,3
+expand,resource,3
+distribute,them,3
+receive,resource,3
+execute,add,3
+reach,scale,3
+expand,pod,3
+involve,process,3
+change,version,3
+monitor,change,3
+perform,update,3
+involve,stopping,3
+require,mechanism,3
+support,policy,3
+transfer,leader,3
+avoid,situation,3
+form,group,3
+promote,management,3
+tune,resource,3
+deploy,xline,3
+explore,update,3
+make,preparation,3
+have,moment,3
+leverage,part,3
+serve,model,3
+revolutionize,way,3
+revolutionize,gpus,3
+accelerate,task,3
+combine,capability,3
+analyze,novel,3
+orchestrate,workload,3
+present,set,3
+enable,container,3
+leverage,accelerator,3
+combine,best,3
+power,generation,3
+understand,plugin,3
+expose,number,3
+consume,resource,3
+report,issue,3
+include,discovery,3
+configure,resource,3
+maintain,stability,3
+configure,prerequisite,3
+have,driver,3
+install,toolkit,3
+configure,runtime,3
+use,eks,3
+handle,version,3
+handle,these,3
+use,node,3
+deploy,plugin,3
+install,daemonset,3
+use,helm,3
+install,version,3
+upgrade,release,3
+give,setup,3
+customize,chart,3
+see,set,3
+add,taint,3
+configure,toleration,3
+schedule,plugin,3
+configure,sharing,3
+optimize,utilization,3
+share,gpu,3
+interleave,execution,3
+allocate,slice,3
+require,power,3
+do,nothing,3
+isolate,workload,3
+grant,that,3
+grant,replica,3
+access,gpu,3
+execute,thing,3
+mind,this,3
+mitigate,downside,3
+support,mig,3
+partition,gpu,3
+ensure,isolation,3
+give,control,3
+provide,protection,3
+read,more,3
+use,mixed,3
+expose,type,3
+require,that,3
+enable,process,3
+share,context,3
+allow,sharing,3
+run,kernel,3
+allocate,cpu,3
+split,gpu,3
+enforce,limit,3
+allocate,gpus,3
+include,toleration,3
+schedule,pod,3
+request,toleration,3
+abstract,complexity,3
+scratch,surface,3
+check,part,3
+troubleshoot,issue,3
+check,resource,3
+expand,footprint,3
+adopt,technology,3
+focus,underscore,3
+focus,organization,3
+reduce,waste,3
+consider,model,3
+reach,point,3
+avoid,investment,3
+incorporate,them,3
+secure,workload,3
+add,complexity,3
+factor,that,3
+run,kubernetes,3
+have,team,3
+build,kubernetes,3
+understand,nuance,3
+hire,team,3
+run,which,3
+share,way,3
+reduce,lifting,3
+drive,business,3
+maintain,control,3
+facilitate,migration,3
+have,merit,3
+expose,you,3
+offer,control,3
+point,conflict,3
+point,something,3
+pay,le,3
+add,pressure,3
+have,customer,3
+implement,quota,3
+allow,they,3
+spend,what,3
+use,water,3
+realize,that,3
+incentivize,you,3
+build,thing,3
+counteract,risk,3
+implement,control,3
+scrutinize,operation,3
+enforce,program,3
+encourage,sense,3
+optimize,investment,3
+have,rigor,3
+push,thing,3
+test,they,3
+consider,value,3
+adopt,inform,3
+capture,nuance,3
+achieve,balance,3
+exhort,responsibility,3
+bring,stakeholder,3
+finance,people,3
+establish,policy,3
+enforce,that,3
+increase,visibility,3
+find,way,3
+own,application,3
+educate,them,3
+tell,you,3
+support,client,3
+leverage,kubernetes,3
+manage,expense,3
+see,that,3
+define,kpis,3
+draw,budget,3
+plan,hiring,3
+decide,line,3
+have,way,3
+track,aspect,3
+call,whatever,3
+use,kubernetes,3
+take,responsibility,3
+cost,management,3
+cost,timely,3
+avoid,increase,3
+showcase,impact,3
+see,lambdatest,3
+secure,funding,3
+lead,development,3
+share,insight,3
+navigate,challenge,3
+adopt,principle,3
+optimize,resource,3
+save,cost,3
+highlight,journey,3
+emphasize,optimization,3
+outline,approach,3
+navigate,hurdle,3
+discuss,solution,3
+expand,offering,3
+support,customer,3
+reflect,decision,3
+release,kubernetes,3
+manage,cluster,3
+create,question,3
+spend,much,3
+divide,cost,3
+drain,leader,3
+invest,amount,3
+understand,invoice,3
+lose,control,3
+source,tool,3
+produce,consumption,3
+identify,driver,3
+build,team,3
+manage,center,3
+achieve,visibility,3
+create,framework,3
+align,report,3
+see,adoption,3
+have,product,3
+implement,tagging,3
+utilize,pool,3
+determine,allocation,3
+lay,groundwork,3
+support,isolation,3
+simplify,control,3
+make,analysis,3
+vectorize,data,3
+provide,feedback,3
+involve,action,3
+promote,issue,3
+find,opportunity,3
+manage,cpu,3
+change,approach,3
+integrate,element,3
+enable,personnel,3
+manipulate,data,3
+underscore,monitoring,3
+foster,collaboration,3
+bridge,divide,3
+optimize,cost,3
+run,cluster,3
+build,awareness,3
+inform,objective,3
+try,lot,3
+get,understanding,3
+implement,tracking,3
+distribute,tracing,3
+monitor,request,3
+pinpoint,opportunity,3
+increase,accountability,3
+enable,thing,3
+underpin,metric,3
+track,progress,3
+make,cost,3
+control,them,3
+impact,cost,3
+enable,recommendation,3
+share,approach,3
+observe,attribute,3
+observe,pricing,3
+take,path,3
+show,team,3
+impact,resource,3
+provide,feature,3
+yield,saving,3
+realize,this,3
+implement,approach,3
+affect,production,3
+implement,budget,3
+justify,solution,3
+allocate,amount,3
+alert,you,3
+examine,issue,3
+safeguard,integrity,3
+encourage,practice,3
+encourage,approach,3
+target,place,3
+understand,extent,3
+ingrain,overspending,3
+manage,kubernetes,3
+take,approach,3
+lack,what,3
+overspend,request,3
+lack,awareness,3
+build,culture,3
+share,information,3
+create,space,3
+get,everyone,3
+share,plan,3
+plan,kind,3
+spur,understanding,3
+see,picture,3
+feel,pain,3
+share,member,3
+regard,kubernetes,3
+publish,discovery,3
+influence,everything,3
+reveal,impact,3
+address,paradox,3
+measure,value,3
+calculate,value,3
+multiply,price,3
+hit,snag,3
+estimate,value,3
+recreate,os,3
+represent,cost,3
+face,that,3
+develop,software,3
+highlight,os,3
+enhance,software,3
+meet,threat,3
+develop,engine,3
+maintain,tool,3
+emphasise,need,3
+prevent,incident,3
+create,vulnerability,3
+compromise,software,3
+undervalue,contribution,3
+expose,them,3
+implement,measure,3
+offer,training,3
+develop,process,3
+protect,maintainer,3
+generate,share,3
+lead,pack,3
+create,billion,3
+emphasize,importance,3
+nurture,ecosystem,3
+leverage,option,3
+hold,merit,3
+consider,resource,3
+construct,language,3
+involve,effort,3
+encompass,library,3
+facilitate,development,3
+address,vulnerability,3
+consider,breadth,3
+underscore,role,3
+enhance,infrastructure,3
+reduce,surface,3
+underpin,much,3
+emphasize,commitment,3
+maintain,independence,3
+foster,community,3
+prove,maturity,3
+incubate,status,3
+mark,achievement,3
+prove,growth,3
+solidify,position,3
+foster,tool,3
+enforce,mission,3
+practice,dedication,3
+prevent,entity,3
+dominate,direction,3
+cap,vote,3
+ensure,representation,3
+audit,project,3
+highlight,role,3
+ensure,sustainability,3
+shin,spotlight,3
+quantify,value,3
+celebrate,contribution,3
+highlight,need,3
+secure,future,3
+overstate,value,3
+fuel,innovation,3
+shape,landscape,3
+think,much,3
+host,that,3
+discuss,topic,3
+discuss,theme,3
+poise,that,3
+observe,decision,3
+rock,ecosystem,3
+surround,licensing,3
+change,term,3
+place,code,3
+deem,paywall,3
+affect,handful,3
+turn,solution,3
+spark,amount,3
+signal,crisis,3
+reflect,reality,3
+reflect,need,3
+benefit,source,3
+make,contribution,3
+get,contributor,3
+help,that,3
+use,software,3
+pay,developer,3
+avoid,paywall,3
+go,help,3
+produce,product,3
+provide,project,3
+own,infrastructure,3
+leverage,provider,3
+mean,amazon,3
+need,alternative,3
+see,organization,3
+launch,service,3
+deploy,cloud,3
+see,generation,3
+need,network,3
+limit,model,3
+open,source,3
+see,crop,3
+offer,prediction,3
+treat,model,3
+use,example,3
+envision,world,3
+import,module,3
+deploy,container,3
+require,ecosystem,3
+maintain,software,3
+back,product,3
+surround,model,3
+need,more,3
+require,investment,3
+head,source,3
+fund,source,3
+force,project,3
+introduce,katalyst,3
+overcommitted,memory,3
+hinder,overcommitment,3
+summarize,strategy,3
+introduce,mechanism,3
+improve,limitation,3
+ensure,qos,3
+have,path,3
+do,allocation,3
+evaluate,possibility,3
+meet,condition,3
+attempt,round,3
+try,compaction,3
+attempt,reclaim,3
+scan,zone,3
+retry,allocation,3
+categorize,reclamation,3
+include,following,3
+reclaim,number,3
+awaken,kswapd,3
+reach,watermark,3
+set,interface,3
+constrain,usage,3
+reach,limit,3
+mark,node,3
+prevent,pod,3
+sort,pod,3
+consider,criterion,3
+compare,pod,3
+compare,difference,3
+evict,pod,3
+start,container,3
+affect,order,3
+select,container,3
+set,container,3
+calculate,container,3
+ensure,guarantee,3
+ensure,fairness,3
+make,enhancement,3
+cause,throttling,3
+make,optimization,3
+identify,limitation,3
+reflect,request,3
+run,task,3
+request,amount,3
+consider,priority,3
+disturb,qos,3
+ensure,priority,3
+reach,reclaim,3
+trigger,impact,3
+cause,latency,3
+undergo,discussion,3
+adopt,design,3
+extend,functionality,3
+involve,module,3
+extend,policy,3
+invoke,interface,3
+retrieve,result,3
+execute,action,3
+handle,configuration,3
+implement,action,3
+support,extension,3
+calculate,timing,3
+calculate,limit,3
+bind,pod,3
+report,taint,3
+provide,metric,3
+perform,detection,3
+sense,pressure,3
+trigger,measure,3
+support,dimension,3
+compare,watermark,3
+indicate,pressure,3
+utilize,memory,3
+reclaim,that,3
+affect,inability,3
+compare,supply,3
+calculate,fulfillment,3
+support,measure,3
+avoid,interference,3
+detect,level,3
+forbid,scheduling,3
+prevent,scheduling,3
+prevent,situation,3
+support,feature,3
+enable,scheduler,3
+achieve,prohibition,3
+configure,them,3
+enable,memcg,3
+require,use,3
+affect,usage,3
+release,cache,3
+write,value,3
+block,process,3
+detect,degree,3
+trigger,eviction,3
+support,user,3
+configure,logic,3
+abstract,framework,3
+eviction,policy,3
+consolidate,action,3
+offer,advantage,3
+support,operation,3
+allow,validation,3
+prevent,container,3
+affect,quality,3
+limit,usage,3
+expand,plugin,3
+calculate,amount,3
+write,file,3
+correlate,migration,3
+correlate,performance,3
+prioritize,allocation,3
+achieve,latency,3
+use,advisor,3
+monitor,watermark,3
+adjust,binding,3
+prevent,node,3
+encounter,situation,3
+optimize,method,3
+elaborate,experience,3
+enhance,kernel,3
+write,log,3
+involve,file,3
+require,amount,3
+specify,threshold,3
+require,degradation,3
+configure,strategy,3
+enable,feature,3
+require,patch,3
+enhance,support,3
+decouple,capability,3
+decouple,feature,3
+interference,detection,3
+turn,them,3
+utilize,them,3
+influence,score,3
+introduce,enhancement,3
+ensure,sequence,3
+submit,patch,3
+customize,behavior,3
+define,strategy,3
+release,that,3
+prevent,overcommitment,3
+increase,amount,3
+reference,paper,3
+utilize,framework,3
+detect,pressure,3
+leverage,sub,3
+leverage,module,3
+use,information,3
+offload,memory,3
+use,zram,3
+save,space,3
+elaborate,detail,3
+deploy,summary,3
+deploy,katalyst,3
+manage,million,3
+unify,management,3
+explain,insight,3
+select,task,3
+ensure,consistency,3
+use,code,3
+manage,data,3
+use,them,3
+prevent,disruption,3
+increase,speed,3
+build,which,3
+modify,data,3
+replicate,writes,3
+support,that,3
+manage,capacity,3
+run,query,3
+reduce,complexity,3
+enhance,productivity,3
+identify,activity,3
+add,support,3
+build,capability,3
+take,day,3
+have,ability,3
+set,configuration,3
+have,range,3
+ensure,performance,3
+shed,light,3
+encounter,limitation,3
+employ,technique,3
+distribute,load,3
+handle,request,3
+require,scaling,3
+handle,volume,3
+redistribute,data,3
+place,order,3
+streamline,management,3
+accommodate,requirement,3
+walk,you,3
+take,example,3
+provide,these,3
+provide,consistency,3
+leverage,that,3
+require,access,3
+provide,capability,3
+retrieve,information,3
+add,information,3
+see,blog,3
+optimize,that,3
+provide,interface,3
+leverage,data,3
+provide,response,3
+support,infrastructure,3
+need,tool,3
+keep,system,3
+build,product,3
+create,experience,3
+complete,task,3
+enhance,scalability,3
+enable,team,3
+offer,performance,3
+store,object,3
+specify,that,3
+support,case,3
+establish,standard,3
+provide,support,3
+fault,tolerance,3
+maximize,utilization,3
+improve,productivity,3
+do,thing,3
+keep,track,3
+process,data,3
+perform,validation,3
+use,mode,3
+detect,issue,3
+ensure,integrity,3
+analyze,difference,3
+keep,data,3
+serve,request,3
+create,index,3
+write,record,3
+access,that,3
+stop,backfill,3
+monitor,progress,3
+limit,amount,3
+provide,guarantee,3
+distribute,data,3
+bridge,gap,3
+balance,datanodes,3
+bring,datanodes,3
+reduce,utilization,3
+send,traffic,3
+roll,change,3
+ingest,hardware,3
+run,rule,3
+include,metadata,3
+use,key,3
+update,metadata,3
+populate,row,3
+require,user,3
+throw,challenge,3
+copy,object,3
+create,image,2
+offer,experience,2
+have,understanding,2
+push,state,2
+evolve,product,2
+identify,content,2
+identify,improvement,2
+recommend,image,2
+need,image,2
+outline,solution,2
+deliver,benefit,2
+avoid,data,2
+facilitate,proximity,2
+combine,bigquery,2
+allow,user,2
+transform,data,2
+develop,lightweight,2
+activate,data,2
+make,them,2
+require,analytics,2
+interpret,them,2
+extract,kind,2
+include,standard,2
+protect,information,2
+apply,data,2
+follow,principle,2
+prevent,analysis,2
+analyze,datasets,2
+enable,transfer,2
+extract,insight,2
+preserve,source,2
+use,storage,2
+harness,bigquery,2
+elevate,process,2
+offer,workflow,2
+use,technique,2
+adapt,pattern,2
+withstand,test,2
+show,integration,2
+utilize,strength,2
+enhance,capability,2
+amalgamate,information,2
+facilitate,training,2
+unlock,search,2
+empower,augmentation,2
+centralize,workload,2
+streamline,analysis,2
+overview,goal,2
+create,way,2
+perform,apis,2
+perform,inference,2
+join,result,2
+create,example,2
+activate,apis,2
+enable,step,2
+provide,reference,2
+create,connection,2
+build,bridge,2
+show,detail,2
+give,service,2
+account,permission,2
+access,bucket,2
+need,permission,2
+achieve,listvalue,2
+make,table,2
+manage,off,2
+specify,level,2
+improve,time,2
+achieve,performance,2
+keep,cost,2
+change,datasets,2
+create,metadata,2
+use,functionality,2
+reference,model,2
+reference,listvalue,2
+create,link,2
+create,object,2
+parse,image,2
+extract,content,2
+put,description,2
+create,udf,2
+see,doc,2
+follow,step,2
+grant,service,2
+use,show,2
+reference,function,2
+use,listvalue,2
+demonstrate,power,2
+reference,data,2
+reference,type,2
+reference,case,2
+provide,dataset,2
+contain,id,2
+provide,result,2
+ask,manager,2
+accelerate,design,2
+drive,awareness,2
+generate,demand,2
+increase,adoption,2
+increase,performance,2
+announce,feature,2
+address,some,2
+unlock,functionality,2
+use,recommendation,2
+optimize,cloud,2
+understand,recommendation,2
+change,picker,2
+choose,organization,2
+show,recommendation,2
+add,recommendation,2
+take,pain,2
+provide,compatibility,2
+evolve,platform,2
+impact,user,2
+follow,process,2
+affect,that,2
+break,change,2
+provide,guideline,2
+manage,them,2
+view,them,2
+offer,deprecation,2
+expand,recommender,2
+use,all,2
+replace,any,2
+enforce,principle,2
+need,that,2
+require,premium,2
+view,notification,2
+address,notification,2
+flag,change,2
+identify,that,2
+delete,project,2
+warn,you,2
+prevent,issue,2
+mitigate,misconfigurations,2
+try,feature,2
+have,feedback,2
+introduce,way,2
+detect,misconfigurations,2
+improve,article,2
+leave,cost,2
+transform,experience,2
+give,transparency,2
+describe,problem,2
+receive,list,2
+have,interface,2
+book,garage,2
+save,time,2
+call,garage,2
+outgrow,architecture,2
+launch,infrastructure,2
+build,repareo,2
+use,server,2
+grow,business,2
+add,feature,2
+create,bottleneck,2
+integrate,repareo,2
+see,surge,2
+place,strain,2
+sign,deal,2
+book,installation,2
+handle,increase,2
+bring,benefit,2
+build,architecture,2
+develop,service,2
+place,workload,2
+adjust,system,2
+complete,migration,2
+manage,apis,2
+use,system,2
+cache,number,2
+offer,algorithm,2
+increase,scale,2
+remedy,issue,2
+enjoy,system,2
+handle,fluctuation,2
+meet,surge,2
+handle,period,2
+take,developer,2
+develop,feature,2
+gather,availability,2
+use,infrastructure,2
+enter,period,2
+increase,base,2
+enter,market,2
+enjoy,time,2
+continue,mission,2
+have,provider,2
+move,business,2
+build,strategy,2
+offer,agreement,2
+include,redundancy,2
+introduce,recovery,2
+offer,failover,2
+ensure,continuity,2
+provide,configuration,2
+manage,query,2
+use,enterprise,2
+enable,failover,2
+coordinate,location,2
+provision,capacity,2
+require,customer,2
+duplicate,cluster,2
+promote,region,2
+rout,layer,2
+contain,replica,2
+attach,datasets,2
+swap,role,2
+read,replica,2
+leave,network,2
+provide,availability,2
+define,pair,2
+support,reservation,2
+designate,region,2
+cost,much,2
+include,capacity,2
+purchase,capacity,2
+provision,enterprise,2
+bill,customer,2
+bill,byte,2
+see,pricing,2
+use,transfer,2
+cancel,query,2
+complete,replication,2
+support,configuration,2
+replicate,dataset,2
+use,statement,2
+add,replica,2
+reference,replica,2
+attach,dataset,2
+create,edition,2
+associate,datasets,2
+promote,reservation,2
+perform,this,2
+fail,reservation,2
+make,preview,2
+manage,quickstart,2
+unlock,opportunity,2
+transform,analysis,2
+deliver,outcome,2
+use,pro,2
+reverse,engineer,2
+accelerate,ability,2
+secure,data,2
+use,seclm,2
+manage,risk,2
+secure,journey,2
+support,defender,2
+introduce,offering,2
+announce,availability,2
+protect,system,2
+recognize,risk,2
+provide,taxonomy,2
+recommend,mitigation,2
+announce,offering,2
+support,saif,2
+assess,security,2
+test,defense,2
+implement,way,2
+enhance,defense,2
+streamline,capability,2
+help,data,2
+assess,application,2
+bring,service,2
+transform,operation,2
+identify,vulnerability,2
+remediate,package,2
+announce,capability,2
+implement,saif,2
+fuse,operation,2
+provide,advice,2
+protect,prompt,2
+configure,policy,2
+set,filter,2
+redact,prompt,2
+navigate,user,2
+analyze,event,2
+ask,gemini,2
+create,playbook,2
+construct,one,2
+refine,playbook,2
+simulate,execution,2
+give,boost,2
+drive,excellence,2
+find,answer,2
+manage,volume,2
+introduce,intelligence,2
+bring,learning,2
+protect,billion,2
+search,research,2
+understand,behavior,2
+read,summary,2
+understand,purpose,2
+make,information,2
+get,overview,2
+target,region,2
+gather,intelligence,2
+include,insight,2
+inspect,type,2
+summarize,property,2
+identify,code,2
+understand,threat,2
+matter,most,2
+search,corpus,2
+make,part,2
+have,vision,2
+do,security,2
+offload,task,2
+free,expert,2
+get,update,2
+mitigate,threat,2
+announce,innovation,2
+design,update,2
+design,help,2
+introduce,operation,2
+uncover,threat,2
+unlock,hunting,2
+unveil,feature,2
+generate,detection,2
+share,direction,2
+guide,you,2
+surface,threat,2
+require,engineering,2
+reduce,process,2
+provide,outcome,2
+include,set,2
+detect,threat,2
+include,address,2
+cryptomining,incident,2
+add,detection,2
+provide,coverage,2
+make,threat,2
+elevate,skill,2
+spend,writing,2
+triaging,case,2
+understand,campaign,2
+initiate,sequence,2
+share,update,2
+receive,action,2
+summarize,event,2
+recommend,action,2
+require,expertise,2
+reduce,work,2
+maintain,pipeline,2
+require,engineer,2
+write,logic,2
+ensure,compatibility,2
+extract,pair,2
+consume,task,2
+create,parser,2
+support,log,2
+love,operation,2
+raise,bar,2
+cover,you,2
+offer,cybershield,2
+help,government,2
+attend,rsac,2
+have,challenge,2
+lack,view,2
+operationalize,data,2
+announce,intelligence,2
+combine,depth,2
+include,gemini,2
+provide,search,2
+gain,insight,2
+protect,themselves,2
+provide,two,2
+offer,mean,2
+provide,visibility,2
+combine,them,2
+protect,device,2
+block,attempt,2
+connect,dot,2
+attack,campaign,2
+dissect,tactic,2
+use,experience,2
+monitor,group,2
+contextualize,investigation,2
+contribute,indicator,2
+contribute,intelligence,2
+use,intelligence,2
+enrich,base,2
+boast,set,2
+operationalizing,intelligence,2
+slow,ability,2
+evolve,threat,2
+use,gemini,2
+provide,summary,2
+combine,view,2
+supercharge,process,2
+condense,set,2
+analyze,file,2
+challenge,task,2
+assist,professional,2
+combat,malware,2
+offer,window,2
+process,code,2
+take,second,2
+deliver,analysis,2
+offer,tool,2
+automate,fusion,2
+crawl,web,2
+classify,reporting,2
+convert,information,2
+distill,decade,2
+produce,summary,2
+need,training,2
+prioritize,threat,2
+include,operation,2
+read,analysis,2
+strengthen,security,2
+announce,ecosystem,2
+extend,protection,2
+expand,protection,2
+offer,security,2
+provide,secure,2
+add,layer,2
+watermarking,capability,2
+complement,protection,2
+augment,inspection,2
+provide,enterprise,2
+enable,organization,2
+configure,product,2
+target,user,2
+enable,decision,2
+use,policy,2
+enforce,trust,2
+deny,access,2
+deploy,agent,2
+verify,trust,2
+verify,let,2
+block,manage,2
+manage,access,2
+adjust,policy,2
+verify,system,2
+stop,leak,2
+manage,chrome,2
+prevent,leak,2
+block,uploads,2
+prevent,content,2
+detect,information,2
+notify,user,2
+implement,integration,2
+enrol,browser,2
+craft,architecture,2
+offer,ability,2
+adjust,specification,2
+amplify,challenge,2
+require,service,2
+manage,process,2
+bring,effect,2
+align,that,2
+entail,offs,2
+explore,intricacy,2
+accommodate,workload,2
+manage,demand,2
+have,choice,2
+cache,strategy,2
+augment,resource,2
+add,power,2
+add,memory,2
+add,disk,2
+incur,downtime,2
+affect,availability,2
+introduce,replica,2
+require,maintenance,2
+coordinate,period,2
+bring,host,2
+patch,schema,2
+change,example,2
+handle,rdbmss,2
+have,compliance,2
+impact,satisfaction,2
+scale,operation,2
+mitigate,downtime,2
+do,replication,2
+direct,they,2
+limit,scalability,2
+introduce,point,2
+escalate,toil,2
+sharding,challenge,2
+enable,application,2
+bring,set,2
+need,navigation,2
+shard,database,2
+split,they,2
+host,range,2
+spread,traffic,2
+dull,benefit,2
+spread,data,2
+maintain,relationship,2
+span,shard,2
+decrease,integrity,2
+manage,database,2
+require,approach,2
+restore,database,2
+mean,logic,2
+rout,query,2
+handle,failure,2
+maintain,consistency,2
+explode,complexity,2
+add,toil,2
+require,combination,2
+ensure,scalability,2
+ramp,complexity,2
+capture,need,2
+add,scalability,2
+include,detail,2
+impact,ease,2
+increase,demand,2
+elevate,risk,2
+design,database,2
+impose,that,2
+drop,model,2
+question,wisdom,2
+abandon,concept,2
+power,application,2
+eliminate,much,2
+facilitate,architecture,2
+combine,concept,2
+provide,redundancy,2
+want,that,2
+design,application,2
+design,insurance,2
+handle,efficiency,2
+cater,increase,2
+process,request,2
+withdraw,fund,2
+imagine,payment,2
+have,store,2
+create,order,2
+receive,error,2
+lose,request,2
+retry,request,2
+pass,language,2
+pass,caption,2
+create,document,2
+complete,work,2
+change,state,2
+expand,number,2
+offer,delivery,2
+receive,response,2
+raise,connectionerror,2
+add,policy,2
+handle,this,2
+include,connectionerror,2
+add,logic,2
+update,state,2
+track,workflow,2
+use,enum,2
+process,caption,2
+set,stringvalue,2
+track,execution,2
+track,stringvalue,2
+track,call,2
+read,state,2
+use,transaction,2
+process,order,2
+do,stuff,2
+do,account,2
+run,time,2
+make,website,2
+resume,workflow,2
+return,error,2
+receive,one,2
+reject,callback,2
+process,latter,2
+process,callback,2
+discard,callback,2
+confirm,this,2
+query,state,2
+see,invoke,2
+see,workflow,2
+use,sub,2
+trigger,execution,2
+use,delivery,2
+deduplicated,message,2
+use,task,2
+buffer,execution,2
+provide,delivery,2
+have,deduplication,2
+outline,scenario,2
+need,processing,2
+provide,idea,2
+define,configuration,2
+manage,workload,2
+separate,resource,2
+provision,resource,2
+use,scope,2
+access,namespaces,2
+access,bookstore,2
+have,frontend,2
+apply,default,2
+install,sync,2
+fetch,manifest,2
+fetch,branch,2
+offer,way,2
+configure,manifest,2
+configure,sync,2
+integrate,sync,2
+apply,policy,2
+treat,team,2
+manage,tenancy,2
+define,namespaces,2
+apply,scope,2
+label,applying,2
+namespaces,bookstore,2
+utilize,label,2
+apply,networkpolicies,2
+apply,name,2
+apply,object,2
+apply,they,2
+provision,networkpolicy,2
+remove,namespaces,2
+extend,concept,2
+apply,resourcequota,2
+use,reposync,2
+target,fleet,2
+target,scope,2
+grant,permission,2
+leverage,namespaceselector,2
+reference,repository,2
+contain,configmap,2
+apply,configmap,2
+support,approach,2
+provide,solution,2
+explore,scenario,2
+automate,provisioning,2
+ensure,setup,2
+visit,repository,2
+locate,setting,2
+create,secret,2
+store,credential,2
+see,overview,2
+model,process,2
+create,model,2
+rework,them,2
+need,model,2
+require,technology,2
+offer,opportunity,2
+analyze,example,2
+understand,data,2
+generate,layout,2
+implement,model,2
+use,llm,2
+use,bean,2
+provide,platform,2
+access,model,2
+take,screenshot,2
+contain,relationship,2
+create,statement,2
+take,image,2
+include,rule,2
+follow,that,2
+capture,learning,2
+update,prompt,2
+provide,description,2
+create,ddl,2
+follow,rule,2
+guide,command,2
+check,this,2
+add,option,2
+add,table,2
+add,null,2
+leave,statement,2
+order,statement,2
+generate,that,2
+check,work,2
+encounter,error,2
+find,float,2
+have,constraint,2
+influence,table,2
+null,table,2
+null,summary,2
+null,sale,2
+null,name,2
+add,reference,2
+generate,output,2
+leave,side,2
+do,listvalue,2
+use,python,2
+streamline,creation,2
+create,thousand,2
+leverage,process,2
+speed,workflow,2
+find,code,2
+use,capability,2
+see,documentation,2
+apply,model,2
+operationalize,workflow,2
+make,demo,2
+watch,video,2
+build,analytics,2
+launch,abstraction,2
+accelerate,data,2
+open,standard,2
+validate,dataset,2
+realize,gain,2
+recommend,call,2
+use,dataset,2
+include,integration,2
+download,data,2
+use,prerequisite,2
+install,authentication,2
+enable,dataset,2
+use,pytorch,2
+write,implementation,2
+checkout,page,2
+achieve,gain,2
+address,bottleneck,2
+construct,batch,2
+stall,gpu,2
+open,object,2
+provide,throughput,2
+employ,feature,2
+combine,object,2
+download,those,2
+decompose,object,2
+clean,object,2
+speed,metadata,2
+speed,listing,2
+have,million,2
+use,client,2
+use,library,2
+give,dataset,2
+give,try,2
+boost,workflow,2
+learn,capability,2
+learn,session,2
+define,infrastructure,2
+explore,option,2
+reveal,service,2
+provide,workload,2
+provide,functionality,2
+explore,which,2
+show,matrix,2
+use,subnet,2
+define,address,2
+establish,vpc,2
+establish,peering,2
+access,address,2
+enable,consumer,2
+define,network,2
+establish,communication,2
+facilitate,multi,2
+facilitate,tenancy,2
+show,architecture,2
+deploy,resource,2
+deploy,endpoint,2
+leverage,service,2
+get,experience,2
+access,index,2
+share,thought,2
+explore,ebook,2
+support,enterprise,2
+announce,release,2
+deploy,application,2
+use,ray,2
+improve,output,2
+look,article,2
+deliver,information,2
+include,data,2
+guide,llm,2
+reduce,hallucination,2
+provide,material,2
+involve,database,2
+introduce,requirement,2
+serve,llm,2
+retrieve,data,2
+need,infrastructure,2
+access,infrastructure,2
+leverage,framework,2
+involve,number,2
+use,shape,2
+involve,tradeoff,2
+develop,architecture,2
+design,solution,2
+load,embeddings,2
+perform,search,2
+deploy,ray,2
+make,security,2
+filter,content,2
+use,protection,2
+deploy,rag,2
+provide,following,2
+configure,project,2
+embed,pipeline,2
+generate,embeddings,2
+populate,sql,2
+deploy,chatbot,2
+demonstrate,potential,2
+combine,power,2
+handle,task,2
+evolve,solution,2
+add,set,2
+update,database,2
+check,instruction,2
+view,cloud,2
+discuss,rag,2
+raise,family,2
+have,group,2
+introduce,agent,2
+embed,agent,2
+support,those,2
+seek,information,2
+see,reduction,2
+resolve,issue,2
+attract,attention,2
+saw,chance,2
+expand,capability,2
+overhaul,chatbot,2
+implement,chatbot,2
+tackle,project,2
+build,workflow,2
+create,chatbots,2
+create,information,2
+determine,answer,2
+design,any,2
+call,who,2
+complete,project,2
+connect,department,2
+improve,interaction,2
+tell,life,2
+train,people,2
+use,technology,2
+adopt,tool,2
+improve,life,2
+identify,source,2
+find,information,2
+change,hour,2
+update,file,2
+have,time,2
+update,workflow,2
+manage,issue,2
+require,touch,2
+get,answer,2
+inform,next,2
+set,goal,2
+implement,dashboard,2
+refine,support,2
+ask,what,2
+trend,what,2
+gather,data,2
+want,what,2
+augment,staff,2
+transform,service,2
+maintain,momentum,2
+need,catalyst,2
+focus,effort,2
+motivate,team,2
+simplify,work,2
+mean,thing,2
+deliver,product,2
+change,culture,2
+see,purpose,2
+rally,organization,2
+focus,some,2
+launch,experience,2
+adopt,cloud,2
+establish,infrastructure,2
+set,platform,2
+upgrade,service,2
+spark,program,2
+complement,effort,2
+embrace,capability,2
+straddle,system,2
+strain,rate,2
+design,they,2
+cost,saving,2
+bring,focus,2
+benefit,customer,2
+focus,attention,2
+put,spotlight,2
+operate,product,2
+take,what,2
+leave,that,2
+automate,infrastructure,2
+establish,range,2
+delete,all,2
+upgrade,platform,2
+finish,upgrade,2
+unleash,team,2
+modernize,practice,2
+require,set,2
+make,upgrade,2
+finish,migration,2
+maximize,value,2
+support,access,2
+succeed,what,2
+avoid,some,2
+see,block,2
+require,proximity,2
+give,speed,2
+optimize,solution,2
+need,platform,2
+buy,innovation,2
+offer,integration,2
+need,assistance,2
+write,software,2
+bring,assistance,2
+optimize,system,2
+secure,advantage,2
+require,kind,2
+increase,security,2
+commission,consulting,2
+survey,professional,2
+explore,meaning,2
+prioritize,initiative,2
+endpoint,management,2
+automate,task,2
+analyze,behavior,2
+start,journey,2
+adopt,chromeos,2
+visit,three,2
+deliver,endpoint,2
+realize,need,2
+spend,half,2
+reduce,securing,2
+deploy,device,2
+build,chromeos,2
+sandboxed,app,2
+have,perimeter,2
+gain,view,2
+manage,device,2
+revoke,access,2
+wipe,data,2
+deploy,fleet,2
+ship,device,2
+start,who,2
+identify,priority,2
+embrace,application,2
+adopt,application,2
+embrace,web,2
+leave,company,2
+leave,study,2
+departments,application,2
+unlock,power,2
+streamline,support,2
+realize,benefit,2
+achieve,endpoint,2
+benefit,business,2
+slash,cost,2
+deploy,plus,2
+embrace,strategy,2
+check,study,2
+contact,one,2
+affect,people,2
+transform,life,2
+eliminate,seizure,2
+monitor,activity,2
+detect,precursor,2
+prevent,seizure,2
+capture,data,2
+tune,model,2
+identify,time,2
+constrain,learning,2
+constrain,training,2
+slow,optimization,2
+tackle,challenge,2
+leverage,technology,2
+accelerate,capability,2
+identify,one,2
+revolutionize,process,2
+support,workflow,2
+achieve,scalability,2
+identify,feature,2
+have,potential,2
+discover,option,2
+conduct,study,2
+identify,pattern,2
+utilize,capability,2
+employ,ivfflat,2
+execute,search,2
+store,embeddings,2
+facilitate,search,2
+personalize,epilepsy,2
+integrate,infrastructure,2
+direct,effort,2
+emphasize,treatment,2
+emphasize,being,2
+see,information,2
+incorporate,functionality,2
+base,that,2
+utilize,feature,2
+delete,data,2
+have,can,2
+get,file,2
+involve,million,2
+gain,access,2
+perform,attack,2
+hold,hostage,2
+launch,delete,2
+launch,feature,2
+offer,protection,2
+restore,data,2
+optimize,setting,2
+retain,object,2
+need,any,2
+run,restore,2
+copy,they,2
+introduce,delete,2
+select,number,2
+disable,feature,2
+bill,usage,2
+increase,bill,2
+represent,value,2
+provide,that,2
+contain,amount,2
+bill,object,2
+bill,hour,2
+protect,you,2
+ask,yourself,2
+regenerate,that,2
+lose,they,2
+put,relationship,2
+have,level,2
+have,copy,2
+store,backup,2
+afford,protection,2
+perform,backup,2
+consider,storage,2
+leave,delete,2
+have,idea,2
+visualize,them,2
+inspect,handful,2
+get,idea,2
+introduce,metric,2
+break,count,2
+inspect,rate,2
+estimate,impact,2
+calculate,duration,2
+assume,storage,2
+enable,policy,2
+compare,metric,2
+delete,byte,2
+give,month,2
+use,monitoring,2
+create,chart,2
+create,cost,2
+select,explorer,2
+select,mql,2
+enter,query,2
+assume,window,2
+protect,what,2
+publish,script,2
+exceed,percentage,2
+use,script,2
+use,cli,2
+configure,setting,2
+set,language,2
+set,caption,2
+update,delete,2
+update,template,2
+create,template,2
+define,setting,2
+set,duration,2
+extend,technique,2
+instal,version,2
+need,which,2
+implement,policy,2
+use,environment,2
+change,setting,2
+obtain,delete,2
+surpass,act,2
+do,anything,2
+identify,someone,2
+change,configuration,2
+create,role,2
+create,listvalue,2
+manage,setting,2
+create,permission,2
+do,everything,2
+delete,role,2
+apply,analysis,2
+apply,uniform,2
+update,language,2
+use,option,2
+target,subset,2
+update,project,2
+replace,action,2
+run,impact,2
+run,script,2
+update,setting,2
+get,outcome,2
+follow,practice,2
+manage,project,2
+serve,prediction,2
+deliver,impact,2
+include,model,2
+measure,performance,2
+adopt,technique,2
+streamline,experience,2
+manage,model,2
+provide,service,2
+manage,lifecycle,2
+involve,stage,2
+undergo,phase,2
+hinder,leader,2
+address,gap,2
+manage,reliability,2
+visualize,compliance,2
+introduce,framework,2
+package,training,2
+debug,model,2
+give,overview,2
+implement,transformation,2
+provide,user,2
+support,tensorflow,2
+improve,quality,2
+develop,application,2
+validate,output,2
+leverage,capability,2
+build,component,2
+test,application,2
+scale,testing,2
+execute,test,2
+launch,dragoncrawl,2
+enable,them,2
+handle,data,2
+capture,dependency,2
+choose,model,2
+evaluate,model,2
+confuse,model,2
+handle,them,2
+give,name,2
+push,button,2
+do,something,2
+close,app,2
+execute,flow,2
+process,billion,2
+provide,requirement,2
+perform,check,2
+ensure,accuracy,2
+use,component,2
+add,test,2
+help,issue,2
+find,detail,2
+identify,issue,2
+have,metric,2
+measure,coverage,2
+identify,difference,2
+maintain,standard,2
+replay,request,2
+compare,response,2
+log,difference,2
+cache,call,2
+implement,mechanism,2
+store,event,2
+track,metric,2
+configure,alert,2
+use,alert,2
+log,error,2
+use,combination,2
+modify,record,2
+have,flexibility,2
+compare,record,2
+compare,data,2
+hit,limit,2
+scale,job,2
+put,load,2
+cause,problem,2
+have,control,2
+dump,data,2
+cover,aspect,2
+bring,need,2
+affect,latency,2
+write,failure,2
+read,data,2
+do,read,2
+introduce,challenge,2
+cause,issue,2
+maintain,table,2
+cause,regression,2
+identify,bug,2
+maximize,efficiency,2
+build,framework,2
+reduce,usage,2
+implement,system,2
+foster,culture,2
+create,environment,2
+enhance,quality,2
+have,one,2
+see,issue,2
+have,effect,2
+write,traffic,2
+optimize,balancer,2
+initiate,process,2
+request,information,2
+transfer,block,2
+provide,statistic,2
+balance,them,2
+balance,throughput,2
+form,pair,2
+increase,pair,2
+bring,usage,2
+balance,node,2
+add,metric,2
+reduce,capacity,2
+run,service,2
+have,task,2
+collect,sample,2
+use,average,2
+measure,imbalance,2
+reduce,frequency,2
+face,issue,2
+emit,stats,2
+build,aggregation,2
+modify,placement,2
+have,issue,2
+see,case,2
+use,weight,2
+deploy,instance,2
+have,instance,2
+show,example,2
+attach,load,2
+require,trip,2
+serve,rps,2
+prefer,instance,2
+move,workload,2
+build,observability,2
+generate,alert,2
+support,value,2
+tune,they,2
+have,metadata,2
+include,ability,2
+support,normalization,2
+classify,rule,2
+add,metadata,2
+enable,rule,2
+generate,score,2
+add,rule,2
+weight,signal,2
+involve,entity,2
+minimize,positive,2
+resolve,contact,2
+scale,channel,2
+rout,which,2
+track,health,2
+use,protocol,2
+enable,agent,2
+deliver,contact,2
+receive,contact,2
+disconnect,socket,2
+send,message,2
+push,event,2
+direct,traffic,2
+cause,increase,2
+onboard,case,2
+demand,latency,2
+have,threshold,2
+serve,read,2
+build,solution,2
+build,caching,2
+avoid,problem,2
+require,consistency,2
+bypass,cache,2
+update,row,2
+leverage,capture,2
+write,path,2
+write,row,2
+have,key,2
+add,mode,2
+issue,request,2
+have,mechanism,2
+replicate,key,2
+query,database,2
+onboard,user,2
+spend,event,2
+ensure,reliability,2
+configure,detail,2
+apply,transformation,2
+download,structure,2
+get,insight,2
+offer,information,2
+have,insight,2
+cause,failure,2
+resolve,error,2
+serve,which,2
+ask,user,2
+consider,challenge,2
+restrict,access,2
+use,app,2
+throw,that,2
+prompt,user,2
+initiate,challenge,2
+check,condition,2
+verify,amount,2
+generate,feature,2
+hold,metadata,2
+contain,metadata,2
+process,update,2
+compare,metadata,2
+use,presto,2
+query,source,2
+bump,pointer,2
+allocate,object,2
+divide,heap,2
+increase,space,2
+see,impact,2
+improve,performance,2
+drive,evolution,1
+offer,set,1
+cover,lifecycle,1
+empower,uber,1
+productize,application,1
+leverage,michelangelo,1
+advance,model,1
+present,evolution,1
+span,country,1
+serve,trip,1
+take,app,1
+detect,signal,1
+suggest,completion,1
+rank,result,1
+choose,destination,1
+extend,reach,1
+power,chatbot,1
+underpin,flow,1
+necessitate,investment,1
+distribute,methodology,1
+witness,push,1
+boost,performance,1
+represent,development,1
+advance,capability,1
+use,notebook,1
+manage,training,1
+compare,result,1
+create,container,1
+launch,michelangelo,1
+standardize,workflow,1
+build,store,1
+host,feature,1
+provide,api,1
+learn,pyml,1
+speed,cycle,1
+productionizing,model,1
+extend,representation,1
+learn,horovod,1
+learn,michelangelo,1
+uplevel,performance,1
+drive,value,1
+pose,figure,1
+have,standard,1
+measure,spectrum,1
+ignore,metric,1
+result,model,1
+receive,investment,1
+hinder,progress,1
+invest,month,1
+develop,toolkits,1
+train,version,1
+optimize,michelangelo,1
+pose,threat,1
+make,exploration,1
+build,tool,1
+launch,project,1
+architectured,platform,1
+center,michelangelo,1
+enable,architecture,1
+build,some,1
+improve,velocity,1
+enable,technology,1
+enforce,compliance,1
+measure,quality,1
+define,tiering,1
+maximize,impact,1
+leverage,power,1
+leverage,workflow,1
+enable,workflow,1
+support,plug,1
+support,subset,1
+bring,component,1
+take,api,1
+take,principle,1
+prioritize,solution,1
+codify,practice,1
+feature,monitoring,1
+define,apis,1
+do,lifting,1
+handle,inference,1
+adopt,kubernetes,1
+adopt,pattern,1
+follow,convention,1
+standardize,operation,1
+leverage,machinery,1
+support,mutation,1
+support,checkpoint,1
+avoid,execution,1
+execute,step,1
+manage,service,1
+show,design,1
+simplify,dependency,1
+hinder,figure,1
+launch,score,1
+monitor,dimension,1
+ensure,approach,1
+leverage,concept,1
+differentiate,case,1
+introduce,project,1
+tiering,scheme,1
+serve,function,1
+influence,operation,1
+encompass,case,1
+regard,allocation,1
+elevate,quality,1
+launch,canvas,1
+apply,practice,1
+enforce,control,1
+include,framework,1
+customizable,template,1
+provide,code,1
+provide,management,1
+use,bazel,1
+provide,developing,1
+automate,deployment,1
+index,metadata,1
+leverage,bazel,1
+enable,environment,1
+run,them,1
+learn,representation,1
+hinder,adoption,1
+require,support,1
+implement,dsl,1
+bundle,transformation,1
+eliminate,source,1
+transform,feature,1
+provide,flexibility,1
+define,transformation,1
+combine,graph,1
+leverage,horovod,1
+distribute,training,1
+wrap,training,1
+use,syntax,1
+replace,trainer,1
+tune,solution,1
+allow,training,1
+scale,number,1
+increase,coverage,1
+require,function,1
+design,figure,1
+serve,most,1
+integrate,triton,1
+support,framework,1
+require,resource,1
+use,resource,1
+build,layer,1
+build,cluster,1
+hide,region,1
+leverage,pattern,1
+support,spark,1
+have,parameter,1
+train,trip,1
+develop,studio,1
+unify,offering,1
+provide,experience,1
+provide,flow,1
+cover,step,1
+cover,cycle,1
+boast,array,1
+manage,entity,1
+debug,capability,1
+accelerate,recovery,1
+cover,workflow,1
+facilitate,task,1
+construct,pipeline,1
+manage,pipeline,1
+undergo,process,1
+possess,capacity,1
+transform,interaction,1
+investigate,use,1
+boost,productivity,1
+streamline,operation,1
+improve,product,1
+show,value,1
+learn,figure,1
+need,access,1
+host,llm,1
+have,performance,1
+require,knowledge,1
+leverage,wealth,1
+achieve,level,1
+host,model,1
+develop,gateway,1
+access,llm,1
+safeguard,privacy,1
+ensure,tracking,1
+attribute,usage,1
+categorize,data,1
+send,input,1
+accelerate,development,1
+extend,michelangelo,1
+support,capability,1
+feature,collection,1
+explore,information,1
+initiate,workflow,1
+offer,selection,1
+enhance,versatility,1
+compare,llm,1
+evaluate,improvement,1
+save,template,1
+enable,serving,1
+implement,enhancement,1
+serve,stack,1
+implement,trainer,1
+utilize,source,1
+store,llm,1
+support,parallelism,1
+constrain,size,1
+allow,parameter,1
+integrate,deepspeed,1
+enable,parallelism,1
+eliminate,limitation,1
+provision,cluster,1
+set,stage,1
+share,advancement,1
+emphasize,enhancement,1
+institute,platform,1
+build,infrastructure,1
+comprise,team,1
+offer,layer,1
+access,component,1
+design,architecture,1
+allow,adoption,1
+maintain,performance,1
+create,project,1
+guide,allocation,1
+provide,developer,1
+provide,expertise,1
+drive,standardization,1
+build,trust,1
+cultivate,culture,1
+check,website,1
+build,community,1
+accelerate,advancement,1
+develop,idea,1
+enhance,experience,1
+strengthen,quality,1
+take,challenge,1
+encompass,thousand,1
+encompass,experiment,1
+carry,testing,1
+offer,scalability,1
+recur,update,1
+hinder,adaptability,1
+hire,tester,1
+create,dragoncrawl,1
+bring,testing,1
+test,some,1
+maintain,them,1
+block,bug,1
+save,thousand,1
+cover,introduction,1
+cover,dive,1
+touch,little,1
+learn,nuance,1
+generate,text,1
+limit,capability,1
+summarize,document,1
+create,content,1
+involve,architecture,1
+adept,which,1
+get,output,1
+formulate,testing,1
+encounter,obstacle,1
+complete,test,1
+need,context,1
+provide,dragoncrawl,1
+interact,element,1
+combine,strategy,1
+mask,word,1
+alter,order,1
+enable,model,1
+learn,prediction,1
+gain,understanding,1
+surpass,model,1
+offer,language,1
+find,place,1
+obtain,embeddings,1
+perceive,language,1
+frame,evaluation,1
+mimic,way,1
+put,effort,1
+choose,book,1
+make,effort,1
+choose,action,1
+find,book,1
+take,handful,1
+show,ability,1
+pinpoint,option,1
+understand,language,1
+summarize,finding,1
+use,embeddings,1
+need,tuning,1
+choose,what,1
+relate,some,1
+set,location,1
+connect,rider,1
+expect,what,1
+match,rider,1
+tune,location,1
+get,result,1
+debug,artifact,1
+have,condition,1
+choose,ride,1
+open,calendar,1
+choose,date,1
+call,example,1
+popularize,concept,1
+add,bit,1
+fool,model,1
+rid,model,1
+do,training,1
+add,book,1
+add,trip,1
+load,screen,1
+have,that,1
+figure,them,1
+run,dragoncrawl,1
+afford,route,1
+train,dragon,1
+skip,thing,1
+confirm,thing,1
+see,article,1
+trust,model,1
+discuss,guardrail,1
+prevent,hallucination,1
+harm,dragoncrawl,1
+reduce,variability,1
+receive,output,1
+return,response,1
+return,touch,1
+output,action,1
+confuse,name,1
+read,action,1
+resolve,confusion,1
+find,action,1
+retry,suggestion,1
+handle,case,1
+output,list,1
+try,action,1
+discuss,scenario,1
+saw,something,1
+set,profile,1
+do,trip,1
+throw,dragoncrawl,1
+select,method,1
+load,blip,1
+restart,app,1
+match,behavior,1
+represent,what,1
+create,script,1
+match,strategy,1
+update,all,1
+encounter,scenario,1
+raise,eyebrow,1
+alert,engineer,1
+file,ticket,1
+trigger,conversation,1
+reproduce,issue,1
+do,attempt,1
+productionized,model,1
+consume,model,1
+get,win,1
+release,them,1
+observe,following,1
+detect,that,1
+maintain,dragoncrawl,1
+spend,hundred,1
+maintain,case,1
+evaluate,dragoncrawl,1
+tweak,code,1
+vary,parameter,1
+guarantee,which,1
+tune,test,1
+handle,resolution,1
+pave,way,1
+unlock,architecture,1
+use,datasets,1
+create,application,1
+tell,dragoncrawl,1
+build,subsystem,1
+empower,developer,1
+build,test,1
+reap,benefit,1
+improve,model,1
+push,quality,1
+increase,combination,1
+bring,bug,1
+reach,user,1
+increase,productivity,1
+build,experience,1
+give,thing,1
+kick,that,1
+fuel,acceleration,1
+thank,researcher,1
+create,mpnet,1
+enable,others,1
+advance,field,1
+send,thank,1
+turn,dragoncrawl,1
+use,openai,1
+operate,line,1
+follow,tenet,1
+maintain,tenet,1
+build,testing,1
+encompass,configuration,1
+support,scale,1
+design,component,1
+embrace,tenet,1
+onboarded,change,1
+support,scaling,1
+require,validation,1
+uphold,principle,1
+implement,check,1
+provide,signoff,1
+onboarded,requirement,1
+have,tool,1
+validate,requirement,1
+isolate,section,1
+verify,function,1
+rectify,error,1
+test,unit,1
+ensure,service,1
+test,case,1
+include,input,1
+execute,process,1
+run,suite,1
+use,version,1
+compare,these,1
+report,failure,1
+update,test,1
+reflect,behavior,1
+introduce,problem,1
+perform,type,1
+prevent,propagation,1
+deploy,they,1
+enrich,detail,1
+generate,transaction,1
+enable,mitigation,1
+determine,completeness,1
+comprehend,coverage,1
+develop,tool,1
+automate,detection,1
+ensure,launch,1
+disrupt,process,1
+lack,communication,1
+rout,launch,1
+validate,report,1
+cover,scenario,1
+guarantee,integration,1
+disrupt,functionality,1
+undergo,validation,1
+indicate,approval,1
+require,authorization,1
+utilize,job,1
+reinforce,rigor,1
+contradict,protocol,1
+bypass,approval,1
+raise,flag,1
+employ,type,1
+choose,which,1
+impact,number,1
+get,assurance,1
+provide,assurance,1
+implement,change,1
+aggregate,validation,1
+catch,issue,1
+roll,build,1
+deploy,candidate,1
+pass,traffic,1
+compare,output,1
+spot,anomaly,1
+record,pair,1
+involve,examination,1
+determine,level,1
+certify,readiness,1
+replay,traffic,1
+sample,fraction,1
+distribute,replay,1
+reduce,call,1
+limit,scope,1
+make,call,1
+avoid,call,1
+minimize,cost,1
+keep,period,1
+clean,data,1
+lack,ability,1
+develop,mechanism,1
+sample,distribution,1
+develop,request,1
+log,discrepancy,1
+scrutinize,discrepancy,1
+represent,entry,1
+gauge,confidence,1
+compare,comparison,1
+compare,transaction,1
+include,transaction,1
+conduct,analysis,1
+use,query,1
+identify,discrepancy,1
+adjust,confidence,1
+process,that,1
+log,them,1
+contain,attribute,1
+run,workflow,1
+make,timestamp,1
+contain,record,1
+capture,anomaly,1
+write,query,1
+reduce,confidence,1
+stray,confidence,1
+define,threshold,1
+ensure,evaluation,1
+improve,build,1
+deploy,build,1
+ensure,deployment,1
+increase,rate,1
+incorporate,deployment,1
+facilitate,release,1
+enable,identification,1
+employ,approach,1
+test,traffic,1
+propagate,build,1
+ensure,process,1
+alert,platform,1
+consume,data,1
+configure,metric,1
+pause,pipeline,1
+indicate,issue,1
+have,dlq,1
+handle,event,1
+have,event,1
+investigate,cause,1
+ingest,them,1
+configure,dashboard,1
+monitor,table,1
+prioritize,issue,1
+cause,improvement,1
+flag,issue,1
+tag,alert,1
+span,range,1
+chec,event,1
+receive,event,1
+process,event,1
+account,event,1
+log,event,1
+indicate,processing,1
+leverage,strategy,1
+achieve,milestone,1
+reduce,number,1
+reflect,dedication,1
+enable,closure,1
+bolster,confidence,1
+demonstrate,commitment,1
+report,generation,1
+set,standard,1
+meet,challenge,1
+exemplify,commitment,1
+add,functionality,1
+support,correction,1
+support,journey,1
+refine,strategy,1
+underline,importance,1
+explore,ledgerstore,1
+move,entry,1
+make,petabyte,1
+cause,disruption,1
+learn,what,1
+use,dynamodb,1
+keep,week,1
+use,blobstore,1
+use,lsg,1
+alter,record,1
+use,signature,1
+keep,storage,1
+suit,lsg,1
+simplify,code,1
+maintain,service,1
+promise,lag,1
+give,latency,1
+correct,problem,1
+backfilled,record,1
+handle,load,1
+do,check,1
+return,that,1
+disrupt,traffic,1
+see,corruption,1
+give,nine,1
+expect,corruption,1
+flag,them,1
+give,result,1
+collect,data,1
+slow,project,1
+force,you,1
+suspect,that,1
+mean,cost,1
+outweigh,cost,1
+duplicate,traffic,1
+monitor,lsg,1
+write,that,1
+develop,code,1
+reuse,that,1
+fix,them,1
+give,guarantee,1
+skip,record,1
+cover,data,1
+shadow,validation,1
+tackle,that,1
+require,data,1
+distribute,shuffle,1
+find,record,1
+use,output,1
+use,offering,1
+encounter,that,1
+create,attack,1
+find,bottleneck,1
+generate,traffic,1
+need,day,1
+handle,rate,1
+overload,system,1
+run,backfills,1
+break,backfill,1
+complete,batch,1
+dump,statistic,1
+aggregate,number,1
+check,progress,1
+update,record,1
+lower,risk,1
+tweak,that,1
+use,ratelimiter,1
+monitor,state,1
+adjust,rps,1
+have,bound,1
+need,ability,1
+get,load,1
+keep,size,1
+have,file,1
+list,them,1
+run,command,1
+need,kind,1
+stop,job,1
+ignore,them,1
+dump,record,1
+monitor,statistic,1
+fix,problem,1
+make,progress,1
+put,that,1
+keep,log,1
+use,limiter,1
+produce,that,1
+rate,limit,1
+rate,part,1
+produce,most,1
+find,data,1
+remove,fallback,1
+flag,that,1
+check,lsg,1
+take,backup,1
+drop,table,1
+cover,migration,1
+do,migration,1
+mark,migration,1
+name,mark,1
+connect,world,1
+make,billion,1
+make,merchant,1
+provide,completeness,1
+look,ledger,1
+index,hundred,1
+discuss,background,1
+cover,significance,1
+power,trillion,1
+explore,them,1
+handle,flow,1
+use,uber,1
+place,hold,1
+convert,hold,1
+take,trip,1
+serve,hold,1
+take,while,1
+make,charge,1
+perform,write,1
+guarantee,read,1
+use,commit,1
+commit,intent,1
+handle,that,1
+guarantee,consistency,1
+commit,flow,1
+handle,intent,1
+delete,them,1
+read,record,1
+read,flow,1
+require,guarantee,1
+read,write,1
+trade,property,1
+achieve,guarantee,1
+fail,write,1
+build,they,1
+cause,availability,1
+leverage,feature,1
+generate,index,1
+increase,cost,1
+offload,ledger,1
+associate,ledger,1
+seal,data,1
+need,class,1
+query,data,1
+do,query,1
+fare,trip,1
+model,this,1
+develop,index,1
+provide,construct,1
+mean,former,1
+control,order,1
+provide,way,1
+require,mode,1
+configure,mode,1
+adjust,capacity,1
+correlate,time,1
+partition,data,1
+cause,partition,1
+have,restriction,1
+assume,trip,1
+partition,item,1
+choose,value,1
+avoid,splitting,1
+partition,table,1
+say,minute,1
+write,index,1
+do,write,1
+affect,traffic,1
+distribute,traffic,1
+reduce,partitioning,1
+delete,table,1
+offload,index,1
+need,they,1
+handle,throughput,1
+accept,writes,1
+architected,backend,1
+improve,design,1
+overcome,downside,1
+leverage,property,1
+partition,entry,1
+distribute,most,1
+involve,scanning,1
+control,boundary,1
+sort,data,1
+perform,gather,1
+obtain,entry,1
+fix,number,1
+determine,number,1
+simplify,design,1
+simplify,figure,1
+define,index,1
+modify,some,1
+evolve,case,1
+need,mechanism,1
+orchestrate,cycle,1
+validate,them,1
+swap,index,1
+decommission,index,1
+backfills,them,1
+plug,logic,1
+backfilled,validation,1
+backfilled,index,1
+order,checksum,1
+compare,them,1
+identify,figure,1
+miss,entry,1
+measure,success,1
+detect,inconsistency,1
+notice,incident,1
+move,index,1
+operate,ledgerstore,1
+build,support,1
+access,source,1
+support,index,1
+maintain,scale,1
+bring,challenge,1
+see,part,1
+chronicle,migration,1
+embody,value,1
+evolve,docstore,1
+drive,adoption,1
+celebrate,year,1
+employ,model,1
+explore,possibility,1
+support,model,1
+implement,range,1
+scale,system,1
+involve,skus,1
+drive,improvement,1
+cloud,infrastructure,1
+announce,that,1
+drive,goal,1
+establish,system,1
+outline,result,1
+guide,progress,1
+expect,convergence,1
+train,duration,1
+heighten,likelihood,1
+achieve,sla,1
+ensure,outcome,1
+involve,benchmarking,1
+assess,ratio,1
+gauge,efficiency,1
+guarantee,utilization,1
+prevent,gpus,1
+use,job,1
+serve,hour,1
+uphold,rate,1
+maintain,fairness,1
+quantify,metric,1
+prioritize,ecosystem,1
+bolster,velocity,1
+deliver,solution,1
+streamline,model,1
+make,training,1
+serve,deployment,1
+optimize,federation,1
+distribute,asset,1
+lack,capability,1
+create,layer,1
+conceal,cluster,1
+share,detail,1
+expand,infrastructure,1
+accommodate,application,1
+scale,network,1
+implement,connectivity,1
+present,synopsis,1
+emphasize,impact,1
+emphasize,mechanism,1
+reveal,increase,1
+employ,mechanism,1
+duplicate,data,1
+prompt,capacity,1
+double,capacity,1
+build,these,1
+impact,service,1
+demand,memory,1
+restrict,ability,1
+scale,allocation,1
+improve,rate,1
+initiate,effort,1
+double,amount,1
+reuse,dimm,1
+decommission,rack,1
+make,most,1
+detail,gain,1
+kick,effort,1
+rightsize,requirement,1
+request,resource,1
+increase,efficiency,1
+assess,cpu,1
+compare,ratio,1
+use,benchmark,1
+select,skus,1
+consider,factor,1
+test,gpu,1
+employ,library,1
+find,fig,1
+offer,throughput,1
+deliver,throughput,1
+maintain,sla,1
+use,trt,1
+learn,training,1
+serve,evaluation,1
+learn,latency,1
+satisfy,requirement,1
+involve,size,1
+evaluate,framework,1
+present,case,1
+employ,metric,1
+compare,performance,1
+keep,parameter,1
+use,quantization,1
+serve,comparison,1
+use,budget,1
+deliver,increase,1
+underscore,significance,1
+have,solution,1
+outline,framework,1
+impact,scalability,1
+enhance,capacity,1
+boost,efficiency,1
+enable,utilization,1
+result,utilization,1
+find,project,1
+implement,optimization,1
+leave,you,1
+learn,model,1
+demand,tflops,1
+enhance,effectiveness,1
+explore,solution,1
+necessitate,approach,1
+showcased,example,1
+extend,invitation,1
+foster,partnership,1
+urge,engagement,1
+tackle,demand,1
+influence,range,1
+predict,demand,1
+enhance,discovery,1
+refine,time,1
+evaluate,quality,1
+complement,this,1
+overlook,monitoring,1
+neglect,factor,1
+define,dimension,1
+encompass,prototyping,1
+see,figure,1
+integrate,agreement,1
+sustain,this,1
+include,pipeline,1
+distribute,framework,1
+offer,evaluation,1
+design,me,1
+enforce,quality,1
+revolve,concept,1
+reflect,aspect,1
+set,target,1
+set,range,1
+combine,indicator,1
+dictate,status,1
+define,indicator,1
+encapsulate,indicator,1
+represent,level,1
+illustrate,interconnection,1
+necessitate,timeframes,1
+require,attention,1
+meet,benchmark,1
+handle,process,1
+distribute,responsibility,1
+assign,responsibility,1
+receive,alert,1
+tailor,alert,1
+influence,another,1
+trigger,evaluation,1
+address,interconnectedness,1
+depict,interaction,1
+design,indicator,1
+quantify,that,1
+ensure,infrastructure,1
+improve,metric,1
+attach,ownership,1
+define,objective,1
+achieve,objective,1
+cover,that,1
+measure,aspect,1
+qualitymeasures,quality,1
+normalize,row,1
+covariate,distribution,1
+weight,training,1
+retrain,model,1
+validate,correctness,1
+use,interpretabilitymeasures,1
+use,enable,1
+interpretabilitymeasures,presence,1
+normalize,accuracy,1
+enhance,visibility,1
+prioritize,quality,1
+impact,decision,1
+observe,progress,1
+identify,area,1
+enable,retuning,1
+underscore,benefit,1
+monitor,indicator,1
+glean,insight,1
+adopt,system,1
+motivate,practitioner,1
+perceive,measure,1
+integrate,they,1
+necessitate,effort,1
+prioritize,task,1
+balance,standardization,1
+design,framework,1
+permit,customization,1
+reflect,nuance,1
+adopt,error,1
+accommodate,customizations,1
+maintain,approach,1
+manage,framework,1
+develop,matrix,1
+need,attention,1
+maintain,quality,1
+divert,effort,1
+automate,lifecycle,1
+develop,framework,1
+outline,dimension,1
+inspire,framework,1
+accommodate,dimension,1
+evolve,practice,1
+encompass,application,1
+generate,report,1
+review,report,1
+foster,accountability,1
+embed,quality,1
+facilitate,model,1
+own,quality,1
+accomplish,work,1
+apply,scientist,1
+extend,gratitude,1
+promote,adoption,1
+store,file,1
+keep,datanodes,1
+prevent,skew,1
+have,decommissioning,1
+contain,node,1
+have,probability,1
+cause,distribution,1
+skew,datanodes,1
+increase,balance,1
+occupy,datanode,1
+tackle,problem,1
+devise,algorithm,1
+increase,movement,1
+optimize,datanodes,1
+optimize,pair,1
+take,place,1
+balance,size,1
+run,initialization,1
+run,balancer,1
+contact,namenode,1
+obtain,detail,1
+select,block,1
+achieve,distribution,1
+rack,information,1
+plan,movement,1
+coordinate,movement,1
+block,migration,1
+instruct,source,1
+move,block,1
+keep,completion,1
+balance,cluster,1
+have,objective,1
+have,node,1
+transfer,data,1
+improve,throughput,1
+increase,slowness,1
+mention,configs,1
+have,transmission,1
+construct,pair,1
+have,number,1
+face,problem,1
+modify,algorithm,1
+create,pair,1
+create,average,1
+bring,average,1
+have,property,1
+define,percentile,1
+denote,percentile,1
+deploy,command,1
+use,threshold,1
+concentrate,moverthreads,1
+define,balancing,1
+occupy,datanodes,1
+increase,percentage,1
+give,they,1
+move,part,1
+require,balancing,1
+distribute,thread,1
+prioritize,datanodes,1
+ascend,node,1
+prevent,balancing,1
+form,that,1
+calibrate,distribution,1
+create,dashboard,1
+track,performance,1
+calibrate,algorithm,1
+deploy,balancer,1
+take,node,1
+bring,them,1
+have,datanodes,1
+have,bottleneck,1
+have,datanode,1
+reflect,skew,1
+reduce,panel,1
+cause,loss,1
+achieve,efficiency,1
+prevent,probability,1
+deploy,change,1
+raise,patch,1
+dedicate,cluster,1
+apply,tiering,1
+adopt,conversion,1
+save,capacity,1
+describe,journey,1
+utilize,hardware,1
+involve,engineer,1
+deliver,saving,1
+cover,solution,1
+predate,work,1
+repeat,background,1
+recommend,mesh,1
+reuse,dictionary,1
+cover,majority,1
+start,work,1
+analyze,problem,1
+improve,distribution,1
+decentralize,context,1
+decentralize,decision,1
+provide,target,1
+adopt,target,1
+curb,allocation,1
+meet,attempt,1
+risk,reliability,1
+affect,goal,1
+presume,cause,1
+break,slas,1
+represent,usage,1
+distribute,figure,1
+distribute,utilization,1
+utilize,some,1
+imagine,scenario,1
+impact,efficiency,1
+reverse,situation,1
+affect,experience,1
+affect,reliability,1
+avoid,hotspot,1
+mean,waste,1
+chase,them,1
+fix,issue,1
+impact,subset,1
+fix,sibling,1
+mitigate,part,1
+understand,system,1
+measure,system,1
+measure,one,1
+involve,folk,1
+leave,project,1
+have,perspective,1
+measure,outlier,1
+use,utilization,1
+calculate,average,1
+weigh,result,1
+affect,number,1
+exhibit,isolation,1
+have,pattern,1
+consider,long,1
+have,capacity,1
+get,sample,1
+roll,ten,1
+follow,pattern,1
+partition,service,1
+affect,tracking,1
+weigh,workload,1
+affect,weight,1
+affect,score,1
+have,peak,1
+decompose,indicator,1
+track,imbalance,1
+care,minute,1
+roll,data,1
+keep,consideration,1
+create,indicator,1
+calculate,utilization,1
+calculate,core,1
+calculate,wastage,1
+aggregate,them,1
+sum,range,1
+give,weight,1
+explain,indicator,1
+calculate,ratio,1
+make,metric,1
+write,pipeline,1
+process,indicator,1
+slice,data,1
+affect,result,1
+combine,cluster,1
+address,step,1
+build,dashboard,1
+understand,cause,1
+run,thousand,1
+cause,explosion,1
+add,ability,1
+save,usage,1
+leave,stats,1
+introspect,service,1
+enable,visibility,1
+lose,ability,1
+identify,instance,1
+see,usage,1
+break,metric,1
+sort,address,1
+emit,id,1
+provide,lesson,1
+need,observability,1
+draw,analysis,1
+have,visibility,1
+pick,service,1
+analyze,cause,1
+stats,resolution,1
+receive,number,1
+quantify,reason,1
+drive,amount,1
+leave,some,1
+attribute,remainder,1
+show,analysis,1
+give,knob,1
+present,problem,1
+exhibit,cycle,1
+see,spike,1
+aggregate,data,1
+slice,metric,1
+investigate,behavior,1
+reduce,part,1
+start,thread,1
+solve,heterogeneity,1
+require,process,1
+modify,parameter,1
+utilize,set,1
+achieve,cluster,1
+select,type,1
+achieve,imbalancing,1
+choose,figure,1
+choose,change,1
+require,change,1
+deliver,change,1
+kernel,incompatibility,1
+experience,issue,1
+trigger,issue,1
+mean,visibility,1
+fix,these,1
+detect,all,1
+originate,work,1
+give,capacity,1
+have,limitation,1
+preserve,timestamps,1
+handle,restarts,1
+break,collection,1
+relate,aspect,1
+trust,human,1
+ask,owner,1
+roll,fix,1
+receive,answer,1
+decide,imbalance,1
+follow,assignment,1
+pick,host,1
+change,model,1
+roll,solution,1
+turn,zone,1
+guarantee,host,1
+set,weight,1
+take,request,1
+calculate,weight,1
+do,work,1
+rout,zone,1
+ease,imbalance,1
+do,balancing,1
+mitigate,majority,1
+require,update,1
+resize,them,1
+replace,hardware,1
+adjust,weight,1
+solve,drawback,1
+collect,type,1
+update,load,1
+provide,info,1
+treat,instance,1
+balance,ratio,1
+balance,adjusts,1
+reduce,imbalance,1
+introduce,type,1
+assist,balancer,1
+affect,state,1
+reduce,size,1
+inspire,approach,1
+make,choice,1
+relate,change,1
+simplify,approach,1
+discover,post,1
+use,number,1
+report,utilization,1
+base,utilization,1
+track,what,1
+track,target,1
+collect,stats,1
+add,dependency,1
+use,integer,1
+allow,override,1
+change,code,1
+use,indicator,1
+reflect,load,1
+have,integer,1
+have,case,1
+cause,incident,1
+keep,score,1
+scale,load,1
+discover,load,1
+refresh,state,1
+implement,penalty,1
+lose,selection,1
+reduce,value,1
+change,this,1
+reduce,score,1
+use,life,1
+report,value,1
+push,request,1
+receive,reward,1
+commit,part,1
+attach,data,1
+collect,state,1
+collect,status,1
+distribute,change,1
+operate,mesh,1
+push,rps,1
+saw,cost,1
+discover,this,1
+average,response,1
+fix,skews,1
+lack,component,1
+require,cooperation,1
+require,work,1
+plug,middleware,1
+migrate,service,1
+have,reason,1
+write,post,1
+meet,goal,1
+underutilized,most,1
+have,buffer,1
+consume,time,1
+add,component,1
+utilize,fact,1
+know,address,1
+add,weight,1
+have,environment,1
+serve,procedure,1
+represent,load,1
+find,parameter,1
+see,benefit,1
+optimize,service,1
+have,microservices,1
+onboarding,top,1
+give,majority,1
+prove,balancing,1
+onboarded,service,1
+find,type,1
+roll,alb,1
+mix,number,1
+roll,onboarding,1
+tweak,solution,1
+handle,service,1
+serve,rate,1
+warm,service,1
+seed,weight,1
+leave,core,1
+find,this,1
+require,setting,1
+avoid,scenario,1
+explore,change,1
+overwrite,provider,1
+emit,metric,1
+deliver,win,1
+run,container,1
+start,project,1
+lack,tool,1
+realize,way,1
+win,argument,1
+prioritize,work,1
+set,infrastructure,1
+set,right,1
+use,warehouse,1
+get,question,1
+add,workarounds,1
+get,conclusion,1
+base,observation,1
+build,understanding,1
+spend,week,1
+implement,alb,1
+make,bet,1
+avoid,rewrite,1
+derail,project,1
+thank,palayadi,1
+roll,yarpc,1
+license,scale,1
+ask,analyst,1
+contain,phrase,1
+parse,rule,1
+automate,process,1
+apply,extraction,1
+enhance,metadata,1
+reduce,positive,1
+ruleset,process,1
+involve,step,1
+distribute,rule,1
+modify,they,1
+think,rule,1
+undesired,alert,1
+protect,pool,1
+detect,attack,1
+target,sharing,1
+use,knob,1
+categorize,rule,1
+define,category,1
+define,do,1
+include,activity,1
+place,rule,1
+segregate,rule,1
+see,activity,1
+name,option,1
+classify,activity,1
+support,flexibility,1
+optimize,rulesets,1
+inspect,rule,1
+exist,keyword,1
+filter,rule,1
+provide,advantage,1
+have,http,1
+propose,schema,1
+recognize,need,1
+bring,structure,1
+implement,better,1
+receive,adoption,1
+populate,metadata,1
+limit,effectiveness,1
+use,metadata,1
+use,pair,1
+apply,pair,1
+apply,metadata,1
+set,server,1
+classify,that,1
+make,filtering,1
+include,thing,1
+use,format,1
+specify,string,1
+release,rule,1
+use,algebra,1
+define,string,1
+control,selection,1
+limit,usefulness,1
+contribute,improvement,1
+show,component,1
+discuss,which,1
+do,job,1
+support,filtering,1
+specify,relationship,1
+support,comparison,1
+introduce,ability,1
+introduce,filtering,1
+add,element,1
+apply,match,1
+represent,cf,1
+normalize,cf,1
+attempt,value,1
+infer,particular,1
+augment,metadata,1
+create,ability,1
+analyze,ontology,1
+flow,key,1
+protocols,value,1
+filename,value,1
+load,rule,1
+see,direction,1
+write,majority,1
+target,side,1
+scoped,rule,1
+specify,group,1
+include,variable,1
+normalize,directionality,1
+process,source,1
+use,figure,1
+know,direction,1
+determine,significance,1
+detect,what,1
+consider,rule,1
+detect,traffic,1
+communicate,reality,1
+respond,they,1
+offer,option,1
+modify,ruleset,1
+set,priority,1
+do,expression,1
+add,http,1
+add,nothing,1
+add,high,1
+give,pair,1
+give,malware,1
+remove,pair,1
+remove,metadata,1
+perform,expression,1
+set,keyword,1
+contain,keyword,1
+include,priority,1
+use,value,1
+precede,value,1
+decrease,value,1
+show,figure,1
+show,note,1
+set,metadata,1
+contain,underscore,1
+contain,character,1
+increase,value,1
+set,pair,1
+control,condition,1
+define,rule,1
+define,action,1
+have,rule,1
+apply,action,1
+rule,file,1
+load,file,1
+include,statement,1
+contain,rule,1
+update,rule,1
+deploy,that,1
+receive,score,1
+subject,maintenance,1
+subject,they,1
+include,filtering,1
+avoid,analysis,1
+do,revisiting,1
+align,ruleset,1
+expect,pattern,1
+find,documentation,1
+sense,technology,1
+receive,value,1
+represent,that,1
+quantify,necessity,1
+take,form,1
+mention,pipeline,1
+call,what,1
+group,signal,1
+apply,algorithm,1
+create,alert,1
+play,part,1
+weight,they,1
+make,determination,1
+think,which,1
+adjust,score,1
+base,weighting,1
+involve,correlation,1
+know,that,1
+weight,event,1
+aggregate,signal,1
+identify,event,1
+carry,value,1
+manage,alert,1
+describe,conclusion,1
+describe,rule,1
+apply,algebra,1
+tune,rule,1
+add,value,1
+enable,correlation,1
+have,base,1
+spread,that,1
+divide,base,1
+expect,support,1
+expect,resolution,1
+structure,channel,1
+determine,volume,1
+handle,contact,1
+maintain,cost,1
+have,score,1
+reduce,cpc,1
+serve,rest,1
+achieve,csat,1
+deliver,message,1
+reach,agent,1
+deliver,issue,1
+indicate,number,1
+leave,ops,1
+build,challenge,1
+relay,information,1
+involve,exchange,1
+utilize,ramen,1
+serve,role,1
+allow,communication,1
+demonstrate,rate,1
+prompt,necessity,1
+manage,situation,1
+address,limitation,1
+cover,flow,1
+deliver,event,1
+launch,architecture,1
+support,scalability,1
+upgrade,same,1
+miss,sla,1
+miss,concern,1
+staff,concern,1
+onboarded,contact,1
+deprecate,used,1
+provide,lot,1
+have,debugging,1
+detect,miss,1
+complicate,maintenance,1
+cause,spike,1
+add,proxy,1
+perform,authorization,1
+support,insight,1
+connect,customer,1
+connect,success,1
+identify,agent,1
+need,recalibration,1
+improve,transparency,1
+receive,message,1
+showcased,architecture,1
+have,part,1
+use,end,1
+find,match,1
+find,contact,1
+push,contact,1
+push,pipeline,1
+publish,information,1
+receive,information,1
+load,contact,1
+start,need,1
+safeguard,service,1
+onboarded,traffic,1
+define,number,1
+stick,contact,1
+repurposed,dashboard,1
+view,sla,1
+enable,pong,1
+reattempted,reconnection,1
+fetch,contact,1
+accept,them,1
+push,reliability,1
+send,acknowledgment,1
+reserve,contact,1
+send,heartbeat,1
+send,response,1
+consider,impact,1
+enable,enhancement,1
+use,graphql,1
+utilize,graphql,1
+utilize,call,1
+lead,team,1
+select,subscription,1
+push,data,1
+cover,more,1
+have,downloads,1
+align,option,1
+require,communication,1
+have,fallback,1
+make,difference,1
+increase,availability,1
+prevent,socket,1
+back,reconnects,1
+prevent,reconnects,1
+overwhelm,service,1
+connect,socket,1
+reach,layer,1
+extend,usage,1
+perform,test,1
+provide,customer,1
+predict,performance,1
+establish,test,1
+establish,connection,1
+add,machine,1
+test,capacity,1
+reveal,problem,1
+reverse,traffic,1
+manage,traffic,1
+maintain,latency,1
+encounter,system,1
+do,fix,1
+increase,reliability,1
+clear,issue,1
+prevent,event,1
+finish,work,1
+close,tab,1
+log,agent,1
+trace,logouts,1
+improve,confidence,1
+regain,trust,1
+retry,delivery,1
+bring,number,1
+have,win,1
+have,conclusion,1
+open,door,1
+find,image,1
+store,ten,1
+serve,million,1
+introduce,microservices,1
+generate,workload,1
+persist,data,1
+serve,application,1
+require,throughput,1
+accommodate,need,1
+provide,latency,1
+use,docstore,1
+understand,architecture,1
+divide,docstore,1
+compose,partition,1
+handle,workload,1
+sharded,data,1
+contain,leader,1
+use,raft,1
+optimize,model,1
+squeeze,performance,1
+assign,resource,1
+ensure,durability,1
+solve,issue,1
+multiply,cost,1
+handle,each,1
+overcome,this,1
+make,use,1
+provide,redis,1
+follow,challenge,1
+maintain,cache,1
+maintain,replication,1
+suffer,latency,1
+expend,amount,1
+find,solution,1
+follow,goal,1
+minimize,need,1
+reduce,allocation,1
+stabilize,spike,1
+replace,most,1
+answer,need,1
+reuse,client,1
+release,feature,1
+replace,technology,1
+cache,solution,1
+scale,layer,1
+call,redis,1
+support,way,1
+filter,data,1
+follow,filterfilter,1
+integrate,layer,1
+decouple,cache,1
+scale,either,1
+implement,interface,1
+invalidate,entry,1
+cache,feature,1
+configure,usage,1
+get,item,1
+fetch,menu,1
+implement,read,1
+get,request,1
+enable,caching,1
+get,row,1
+populate,redis,1
+read,path,1
+ensure,invalidation,1
+reflect,change,1
+lower,ttl,1
+reduce,cache,1
+reduce,rate,1
+improve,guarantee,1
+support,update,1
+update,schedule,1
+affect,row,1
+fix,this,1
+leverage,docstore,1
+tail,event,1
+publish,event,1
+materialize,view,1
+validate,consistency,1
+write,consumer,1
+upserts,row,1
+use,binlogs,1
+run,risk,1
+pollute,cache,1
+have,flaw,1
+overwrite,value,1
+retrieve,that,1
+deduplicate,writes,1
+parse,timestamp,1
+see,section,1
+support,custom,1
+support,script,1
+take,parameter,1
+perform,logic,1
+check,value,1
+use,eval,1
+perform,all,1
+invalidate,cache,1
+add,api,1
+invalidate,row,1
+define,term,1
+identify,row,1
+enforce,constraint,1
+compose,which,1
+form,key,1
+cache,read,1
+identify,value,1
+store,key,1
+need,codec,1
+encode,data,1
+accept,that,1
+settle,codec,1
+maintain,isolation,1
+complete,design,1
+verify,consistency,1
+tolerate,failure,1
+tolerate,cache,1
+tolerate,talk,1
+mean,nothing,1
+read,that,1
+read,request,1
+log,row,1
+use,flux,1
+spawn,region,1
+ensure,availability,1
+scale,engine,1
+reclaim,capacity,1
+replicate,content,1
+enhance,component,1
+tail,stream,1
+update,cache,1
+overload,engine,1
+discard,stream,1
+keep,set,1
+cache,result,1
+have,miss,1
+enable,this,1
+write,similar,1
+query,that,1
+find,flag,1
+ignore,row,1
+return,data,1
+impact,redis,1
+generate,number,1
+multiple,cluster,1
+avoid,meltdown,1
+issue,number,1
+create,issue,1
+shard,cluster,1
+sharding,scheme,1
+overload,shard,1
+distribute,request,1
+short,request,1
+avoid,penalty,1
+have,confidence,1
+use,breaker,1
+count,number,1
+count,bucket,1
+compute,number,1
+configure,breaker,1
+configure,fraction,1
+hit,count,1
+trip,breaker,1
+set,timeouts,1
+waste,resource,1
+exhaust,timeout,1
+pass,that,1
+mitigate,issue,1
+configure,timeout,1
+adjust,timeouts,1
+cut,tail,1
+configure,timeouts,1
+adjust,set,1
+allow,timeouts,1
+tune,timeouts,1
+match,latency,1
+allow,framework,1
+build,cache,1
+curb,load,1
+have,guarantee,1
+limit,spike,1
+give,flexibility,1
+drive,rps,1
+redirect,traffic,1
+require,core,1
+serve,hit,1
+support,request,1
+address,one,1
+demand,read,1
+save,resource,1
+improve,cost,1
+like,challenge,1
+reserve,right,1
+indicate,sponsorship,1
+reimagine,way,1
+earn,opportunity,1
+bring,brand,1
+achieve,equilibrium,1
+necessitate,activity,1
+remain,opportunity,1
+introduce,user,1
+promote,offering,1
+pay,these,1
+pay,advertisement,1
+develop,strategy,1
+receive,signal,1
+refine,approach,1
+explore,constraint,1
+gather,signal,1
+enhance,operation,1
+attain,scalability,1
+describe,marketing,1
+represent,system,1
+use,term,1
+offer,outline,1
+take,ride,1
+download,app,1
+mark,conversion,1
+signify,expenditure,1
+transmit,downstream,1
+optimize,performance,1
+enhance,algorithm,1
+adjust,them,1
+affect,capability,1
+influence,influx,1
+last,day,1
+delay,downstream,1
+cause,halt,1
+compromise,ability,1
+feature,schema,1
+undergo,transformation,1
+give,rise,1
+challenge,assumption,1
+dedicate,portion,1
+classify,factor,1
+detect,anomaly,1
+enhance,performance,1
+spend,data,1
+prevent,outage,1
+design,enhancement,1
+design,mar,1
+accommodate,case,1
+cause,slowdown,1
+initiate,upgrade,1
+have,apis,1
+handle,ingestion,1
+introduce,data,1
+onboarding,data,1
+encounter,bug,1
+require,system,1
+import,year,1
+incur,latency,1
+impede,flow,1
+require,expense,1
+reduce,productivity,1
+onboarding,partner,1
+take,week,1
+hinder,capacity,1
+run,ad,1
+complete,process,1
+consume,portion,1
+construct,strategy,1
+construct,mar,1
+necessitate,system,1
+incorporate,nuance,1
+need,process,1
+facilitate,experimentation,1
+seek,data,1
+accelerate,result,1
+employ,architecture,1
+conduct,assessment,1
+streamline,cost,1
+gain,flexibility,1
+play,architecture,1
+build,requirement,1
+envision,system,1
+incorporate,architecture,1
+change,component,1
+separate,intricacy,1
+enable,configurability,1
+handle,format,1
+design,jupiter,1
+manage,scenario,1
+have,scenario,1
+require,integration,1
+architected,platform,1
+accommodate,vendor,1
+integrate,vendor,1
+encounter,source,1
+require,ingestion,1
+implement,source,1
+switch,source,1
+have,integration,1
+detect,trend,1
+implement,process,1
+enable,data,1
+expedite,debugging,1
+dedicate,part,1
+achieve,system,1
+configure,component,1
+develop,library,1
+incorporate,transformation,1
+aggregate,transformation,1
+leverage,library,1
+optimize,process,1
+initiate,transformation,1
+conduct,test,1
+trigger,procedure,1
+transfer,responsibility,1
+eliminate,necessity,1
+phase,impact,1
+phase,system,1
+present,overview,1
+outline,difficulty,1
+obtain,data,1
+retire,system,1
+transition,use,1
+incorporate,enhancement,1
+meet,objective,1
+accelerate,process,1
+amalgamate,them,1
+provide,datasets,1
+expand,platform,1
+extend,appreciation,1
+include,gabale,1
+ensure,success,1
+express,gratitude,1
+unwavering,support,1
+do,primer,1
+compose,infrastructure,1
+run,operation,1
+execute,sqls,1
+allow,scheduling,1
+support,portion,1
+support,thousand,1
+own,which,1
+visit,datacentral,1
+find,metadata,1
+debug,query,1
+leverage,platform,1
+leverage,job,1
+help,them,1
+investigate,breach,1
+support,decision,1
+forecast,requirement,1
+develop,datacentral,1
+spread,ecosystem,1
+tie,metric,1
+view,trend,1
+provide,marker,1
+allow,correlation,1
+build,figure,1
+correlate,utilization,1
+provide,figure,1
+affect,job,1
+cause,degradation,1
+add,monitoring,1
+view,performance,1
+capture,metric,1
+root,issue,1
+suggest,fix,1
+improve,discoverability,1
+improve,identify,1
+surface,cause,1
+provide,explanation,1
+provide,workflow,1
+gather,trace,1
+match,trace,1
+surface,message,1
+parse,log,1
+display,suggestion,1
+enable,failure,1
+indicate,action,1
+drive,help,1
+drive,governance,1
+provide,transparency,1
+equip,stakeholder,1
+dissect,usage,1
+drive,conservation,1
+drive,initiative,1
+attribute,reduction,1
+attribute,resource,1
+take,project,1
+check,pattern,1
+create,ticket,1
+raise,ticket,1
+stop,compute,1
+match,scale,1
+handle,query,1
+read,metric,1
+have,span,1
+handle,growth,1
+minimize,time,1
+mitigate,failure,1
+emit,metadata,1
+have,job,1
+consume,metadata,1
+combine,metadata,1
+serve,variety,1
+support,apis,1
+serve,view,1
+join,data,1
+power,insight,1
+serve,team,1
+provide,reduction,1
+support,team,1
+identify,degradation,1
+migrate,job,1
+observe,increase,1
+provide,analytics,1
+use,datacentral,1
+debug,job,1
+mitigate,incident,1
+plan,toolkit,1
+imply,llc,1
+license,image,1
+encounter,multitude,1
+use,method,1
+use,order,1
+bypass,payment,1
+incur,loss,1
+affect,driver,1
+prioritize,management,1
+reflect,landscape,1
+develop,solution,1
+achieve,following,1
+detect,fraud,1
+drive,detection,1
+give,insight,1
+employ,form,1
+resolve,rule,1
+involve,strategy,1
+verify,legitimacy,1
+enter,cvv,1
+make,transaction,1
+catch,actor,1
+have,rate,1
+apply,challenge,1
+consider,scenario,1
+steal,card,1
+own,that,1
+detect,user,1
+prevent,them,1
+employ,action,1
+decline,request,1
+restrict,payment,1
+avoid,fraud,1
+contact,service,1
+resolve,status,1
+introduce,verification,1
+restrict,who,1
+prove,ownership,1
+throw,action,1
+implement,challenge,1
+use,card,1
+trust,user,1
+pass,challenge,1
+present,user,1
+deem,that,1
+avoid,experience,1
+compromise,mitigation,1
+illustrate,path,1
+integrate,figure,1
+integrate,challenge,1
+request,ride,1
+throw,who,1
+resume,action,1
+design,flow,1
+design,challenge,1
+display,challenge,1
+add,method,1
+raise,flow,1
+raise,challenge,1
+initiate,one,1
+call,service,1
+fetch,feature,1
+send,code,1
+encounter,screen,1
+request,consent,1
+deem,challenge,1
+show,modal,1
+verify,card,1
+ask,they,1
+add,card,1
+have,status,1
+click,card,1
+determine,screen,1
+save,data,1
+consent,authorization,1
+use,they,1
+have,money,1
+complete,transaction,1
+collect,payment,1
+issue,amount,1
+use,authorization,1
+create,grant,1
+supply,amount,1
+contact,issuer,1
+request,authorization,1
+review,statement,1
+enter,amount,1
+update,status,1
+verify,hold,1
+fail,challenge,1
+have,indication,1
+pass,conclusion,1
+tune,experience,1
+create,friction,1
+involve,level,1
+understand,what,1
+expedite,onboarding,1
+share,expertise,1
+support,internship,1
+develop,component,1
+strengthen,platform,1
+make,calculation,1
+predict,outcome,1
+query,store,1
+figure,pipeline,1
+feature,store,1
+use,many,1
+create,own,1
+incorporate,feature,1
+show,feature,1
+serve,feature,1
+add,detail,1
+specify,cassandra,1
+copy,data,1
+join,key,1
+include,info,1
+copy,feature,1
+maintain,audit,1
+push,change,1
+load,metadata,1
+update,validation,1
+pick,validation,1
+incorrect,metadata,1
+change,group,1
+prolong,rollback,1
+dedicate,time,1
+spend,majority,1
+verify,schema,1
+make,error,1
+miss,column,1
+land,change,1
+update,repository,1
+highlight,challenge,1
+build,failure,1
+compound,problem,1
+have,backing,1
+back,which,1
+compose,onlinefeatureservinggroup,1
+define,that,1
+represent,metadata,1
+refer,that,1
+guarantee,sla,1
+back,group,1
+contain,cluster,1
+fetch,value,1
+need,setup,1
+break,setup,1
+simplify,interaction,1
+manage,file,1
+serve,file,1
+cover,metadata,1
+contain,query,1
+generate,figure,1
+expedite,offline,1
+expedite,update,1
+move,system,1
+handle,update,1
+compute,delta,1
+register,update,1
+use,controller,1
+push,update,1
+read,cache,1
+reference,which,1
+fragment,unification,1
+fragment,metadata,1
+consolidate,metadata,1
+deprecate,schema,1
+introduce,wrapper,1
+give,ability,1
+transform,metadata,1
+serve,logic,1
+support,interface,1
+translate,metadata,1
+introduce,switch,1
+tell,wrapper,1
+provide,version,1
+do,rollback,1
+keep,experience,1
+maintain,script,1
+synchronize,metadata,1
+avoid,gap,1
+provide,documentation,1
+onboard,feature,1
+create,correctness,1
+create,metric,1
+articulate,difference,1
+regard,correctness,1
+check,metric,1
+introduce,change,1
+maintain,compatibility,1
+create,wrapper,1
+transition,implementation,1
+facilitate,process,1
+incorporate,itself,1
+incorporate,workflow,1
+guarantee,functionality,1
+conduct,testing,1
+involve,system,1
+encounter,issue,1
+yield,result,1
+define,plan,1
+minimize,risk,1
+migrate,cluster,1
+introduce,validation,1
+do,acknowledgement,1
+do,step,1
+spend,year,1
+rearchitecting,system,1
+give,colleague,1
+make,idea,1
+initiate,idea,1
+cover,image,1
+operate,cluster,1
+span,node,1
+have,user,1
+accommodate,request,1
+schedule,workload,1
+schedule,job,1
+classify,each,1
+comprise,machine,1
+equip,which,1
+have,machine,1
+equip,that,1
+modify,concurrency,1
+carry,activity,1
+improve,fragmentation,1
+give,sense,1
+divide,memory,1
+decrement,pointer,1
+increment,pointer,1
+allocate,what,1
+reference,object,1
+achieve,region,1
+divide,figure,1
+have,region,1
+categorize,region,1
+divide,generation,1
+create,arena,1
+need,survivor,1
+copy,memory,1
+do,object,1
+use,mechanism,1
+increase,age,1
+hit,threshold,1
+call,this,1
+clear,generation,1
+use,stab,1
+consider,object,1
+clean,one,1
+include,region,1
+reduce,fragmentation,1
+determine,size,1
+fulfill,job,1
+use,openjdk,1
+start,mark,1
+look,value,1
+tune,them,1
+tune,version,1
+introduce,ihop,1
+change,all,1
+tune,jdk,1
+calculate,ihop,1
+use,size,1
+remember,mark,1
+sweep,run,1
+list,process,1
+verify,experiment,1
+try,following,1
+affect,user,1
+miss,utilization,1
+know,data,1
+expand,time,1
+do,collection,1
+pause,result,1
+decrease,size,1
+give,that,1
+decrease,waste,1
+release,garbage,1
+do,marking,1
+order,region,1
+choose,one,1
+have,space,1
+clean,that,1
+decrease,that,1
+analyze,log,1
+give,threshold,1
+give,buffer,1
+have,garbage,1
+see,pause,1
+reduce,gc,1
+increase,waste,1
+try,option,1
+test,config,1
+verify,behavior,1
+grab,cluster,1
+see,conclusion,1
+see,gc,1
+get,any,1
+use,flag,1
+add,flag,1
+reduce,rerun,1
+finalize,which,1
+see,collection,1
+reduce,burden,1
+observe,impact,1
+pay,attention,1
+use,heap,1
+use,what,1
+experience,gc,1
+end,flag,1
+improve,all,1
diff --git a/verb_extract.py b/verb_extract.py
new file mode 100644
index 0000000..ce98672
--- /dev/null
+++ b/verb_extract.py
@@ -0,0 +1,212 @@
+import nltk
+import os
+from fetch_exper_data import download_xml, read_xml_from_file, xml_dict_to_article_list
+import spacy
+from bs4 import BeautifulSoup
+
+
+def extract_verb_subject(sentence):
+ """
+ Extracts verbs and their subjects from a sentence.
+
+ Args:
+ sentence: A string representing the sentence to be analyzed.
+
+ Returns:
+ A list of dictionaries, where each dictionary has two keys:
+ - verb: The verb identified in the sentence.
+ - subject: The subject of the verb.
+ """
+ tokens = nltk.word_tokenize(sentence) # Tokenize the sentence
+ pos_tags = nltk.pos_tag(tokens) # Get part-of-speech tags
+
+ verb_subject_pairs = []
+ verb = None
+ for token, pos_tag in pos_tags:
+ if pos_tag.startswith("VB"): # Check if token is a verb
+ verb = token.lower()
+ elif not verb is None and (
+ pos_tag.startswith("NN") or pos_tag.startswith("PRP")
+ ): # Check for nouns or pronouns after verb
+ verb_subject_pairs.append({"verb": verb, "subject": token.lower()})
+ verb = None
+
+ return verb_subject_pairs
+
+
+def test_ver1():
+ nltk.download("averaged_perceptron_tagger")
+ nltk.download("punkt") # Download sentence tokenizer if not already installed
+ # Example usage
+ sentence = "The Microsoft Surface organization exists to create iconic end-to-end experiences across hardware, software, and services that people love to use every day. We believe that products are a reflection of the people who build them, and that the right tools and infrastructure can complement the talent and passion of designers and engineers to deliver innovative products. Product level simulation models are routinely used in day-to-day decision making on design, reliability, and product features. The organization is also on a multi-year journey to deliver differentiated products in a highly efficient manner. Microsoft Azure HPC plays a vital role in enabling this vision. Below is an account of how we were able to do more with less by leveraging the power of simulation and Azure HPC. "
+ verb_subject_pairs = extract_verb_subject(sentence)
+
+ print(
+ verb_subject_pairs
+ ) # Output: [{'verb': 'submitted', 'subject': 'i'}, {'verb': 'improve', 'subject': 'research'}]
+
+
+def extract_verb_object(sentence):
+ """
+ Extracts verbs and their direct objects from a sentence using dependency parsing.
+
+ Args:
+ sentence: A string representing the sentence to be analyzed.
+
+ Returns:
+ A list of dictionaries, where each dictionary has two keys:
+ - verb: The verb identified in the sentence.
+ - object: The direct object of the verb.
+ """
+ doc = nlp(sentence) # Parse the sentence
+
+ verb_object_pairs = []
+ for token in doc:
+ if token.pos_ == "VERB": # Check if token is a verb
+ for child in token.children:
+ if child.dep_ in (
+ "dobj",
+ "nsubjpass",
+ ): # Check for direct object or passive subject
+ verb_object_pairs.append(
+ {"verb": token.text.lower(), "subject": child.text.lower()}
+ )
+ # Consider adding break after appending for efficiency if needed
+
+ return verb_object_pairs
+
+
+def test_ver2():
+ # Example usage
+ sentence1 = "I submitted a proposal that can improve future research"
+ sentence2 = "The proposal was submitted by me"
+ verb_object_pairs1 = extract_verb_object(sentence)
+ print(
+ verb_object_pairs1
+ ) # Output: [{'verb': 'submitted', 'object': 'proposal'}] (may also include "improve" - research)
+ # Note: This code focuses on direct objects. For a wider range of objects, consider additional dependency labels.
+
+
+def remove_tags(html):
+ # parse html content
+ soup = BeautifulSoup(html, "html.parser")
+ for data in soup(["style", "script"]):
+ # Remove tags
+ data.decompose()
+ # return data by retrieving the tag content
+ return " ".join(soup.stripped_strings)
+
+
+def plural_to_singular(word):
+ """
+ Converts a noun to its singular form using NLTK's WordNet.
+
+ Args:
+ word: The word to be converted (assumes it's a noun).
+
+ Returns:
+ The singular form of the word if conversion is successful, otherwise None.
+ """
+ wnl = nltk.WordNetLemmatizer()
+ singular = wnl.lemmatize(word, pos="n") # Lemmatize with noun part-of-speech
+ return (
+ singular if singular != word else word
+ ) # Check if word itself is the singular form
+
+
+def verb_to_base(verb):
+ """
+ Attempts to convert a verb to its base form (lemma) using NLTK's WordNet.
+
+ Args:
+ verb: The verb to be converted.
+
+ Returns:
+ The base form of the verb if conversion is successful, otherwise the original verb.
+ """
+ wnl = nltk.WordNetLemmatizer()
+ base_form = wnl.lemmatize(verb, pos="v") # Lemmatize with verb part-of-speech
+ return (
+ base_form if base_form != verb else verb
+ ) # Check if word itself is the base form
+
+
+def contains_non_letters(string):
+ """
+ Checks if a string contains any characters other than letters (a-z and A-Z).
+
+ Args:
+ string: The string to be checked.
+
+ Returns:
+ True if the string contains non-letters, False otherwise.
+ """
+ for char in string:
+ if not char.isalpha():
+ return True
+ return False
+
+
+def do_extract_for_single_source(url: str, pair_lists: dict) -> dict:
+ """
+ Extracts verb-object pairs from a single source URL and updates a dictionary
+ containing counts of those pairs.
+
+ Args:
+ url: The URL of the source to extract data from (assumed to be XML format).
+ pair_lists: A dictionary that stores counts of verb-object pairs.
+ Keys are formatted as "{verb},{singular_subject}".
+
+ Returns:
+ The updated dictionary `pair_lists` with counts incremented based on
+ extracted verb-object pairs from the source.
+ """
+
+ filename = "exper/raw/" + url.split("/")[-1]
+ download_xml(url=url, path=filename)
+ xml_dict = read_xml_from_file(filename)
+ article_list = xml_dict_to_article_list(
+ xml_dict, ["rss", "channel", "item"], ["title", "description"]
+ )
+ # print(str(article_list))
+ for i in article_list.list:
+ for pair in extract_verb_object(remove_tags(i.content)):
+ # Remove if subject less than 3
+ if len(pair["subject"]) < 3:
+ continue
+ # If key or value contains none letters, continue
+ if contains_non_letters(pair["verb"]) or contains_non_letters(
+ pair["subject"]
+ ):
+ continue
+ tmpStrKey = "{0},{1}".format(
+ verb_to_base(pair["verb"]), plural_to_singular(pair["subject"])
+ )
+ if tmpStrKey in pair_lists.keys():
+ pair_lists[tmpStrKey] += 1
+ else:
+ pair_lists[tmpStrKey] = 1
+ return pair_lists
+
+
+if __name__ == "__main__":
+ nltk.download("wordnet")
+ nlp = spacy.load("en_core_web_sm") # Load the English language model
+ pair_lists = {}
+
+ url_root = os.getenv("RSSHUB_ROOT")
+ assert url_root is not None
+ urllist = [
+ url_root + "/cncf/blog",
+ "https://cloudblog.withgoogle.com/rss",
+ url_root + "/uber/blog",
+ ]
+
+ for i in urllist:
+ pair_lists = do_extract_for_single_source(i, pair_lists)
+
+ sorted_dict = dict(
+ sorted(pair_lists.items(), key=lambda item: item[1], reverse=True)
+ )
+ for elem in sorted_dict.items():
+ print("{0},{1}".format(elem[0], elem[1]))