Database Design

191 posts

datadog3 min readCurated summary

Introducing Husky, Datadog's third-generation event store

Datadog built Husky, a new event-storage system, after its original log architecture struggled with multi-tenant reliability, rapid platform growth, and evolving product requirements. The post explains how Datadog moved from metrics-oriented storage to event storage, introduced custom sharding and routing, and eventually recognized the need for a more flexible system. Husky emerged from these lessons about isolation, scalability, and retaining high-cardinality event data. ## From Metrics to Logs - Metrics systems store pre-aggregated tuples such as `<timeseries_id, timestamp, float64>`. - Aggregation makes metrics extremely efficient: millions of events in a second can become one compact datapoint, often requiring less than two bytes with delta-of-delta encoding. - This model is poorly suited to logs because logs must preserve individual events and their full context. - Metrics typically favor long-lived, low-cardinality dimensions such as: - Datacenter - Service - Pod name - Short-lived, high-cardinality fields such as transaction IDs and packet IDs are usually pre-aggregated or omitted. - Logs instead need to support: - Multi-kilobyte events - High-cardinality values such as UUIDs and stack traces - Arbitrary aggregations performed at query time ## Limitations of the Initial Logs System - Datadog’s first Logs architecture initially worked well but became vulnerable in a multi-tenant environment. - A single unhealthy or overloaded node could degrade service for every tenant in the cluster. - Scaling overloaded clusters could worsen the situation because nodes began streaming data to one another while already handling excessive read and write workloads. - Diagnosing and mitigating these cascading failures was difficult. ## Separating Storage from Clustering Datadog’s second architecture retained the same single-node storage engine but moved clustering responsibilities into dedicated services. - Storage nodes no longer knew about one another and behaved like independent one-node clusters. - Failures were isolated to the tenants assigned to a particular shard instead of spreading across the entire cluster. - A Shard Router: - Read events from Kafka - Reorganized them into shard-based Kafka partitions - Dynamically assigned tenants to an appropriate number of shards based on their recent five-minute data volume - Each shard was consumed by two storage-node replicas for redundancy. - A custom query engine tracked tenant-to-shard assignments, queried the relevant replicas, merged partial aggregates, and produced final results. ## Growth of the Event Platform - The new architecture substantially improved reliability and reduced operational burden. - Datadog expanded the platform beyond Logs to support products including: - Network Performance Monitoring - Real User Monitoring - Continuous Profiler - These products generated structured, multi-kilobyte events with storage and indexing requirements similar to logs. - As usage grew, new problems appeared: - A tenant producing a sudden burst of events could degrade query performance for other tenants sharing its shard. - Product teams requested longer retention for important but infrequently queried data, while still requiring it to remain immediately queryable. - The existing architecture was increasingly difficult to adapt to these isolation, scalability, and retention requirements, motivating the development of Husky. Datadog’s progression shows that event storage cannot simply reuse metrics-oriented designs. Systems must preserve event-level context, isolate tenants from one another, and support changing retention and query requirements as products and workloads evolve.

Read original(opens in new tab)
datadog3 min readCurated summary

How Datadog's IT team automated account inactivity and SaaS spend management

Datadog expanded its Clarity auditing tool into Clarity License Manager (CLM), a system that tracks SaaS usage, reduces licensing costs, and improves security. CLM identifies inactive accounts, notifies employees, automatically deactivates unused access, and restores it quickly when needed. Its microservice architecture and application-specific adapters allow the system to scale across many SaaS products. ## The SaaS License Management Problem - Datadog used many commercial SaaS tools with substantial per-user costs. - License usage data was outdated and collected through quarterly manual audits. - IT Support had to contact employees individually, creating administrative overhead and a poor user experience. - Unused accounts also created security risks, including stale credentials that could be compromised. ## Goals of Clarity License Manager - Monitor and automatically deactivate inactive accounts, especially in sensitive services such as cloud providers. - Reduce the risk of leaked or abused stale credentials. - Limit the potential impact of security incidents. - Lower SaaS spending and support data-driven licensing decisions. - Preserve employee productivity through an easy account restoration process. ## Usage Monitoring and Automated Workflows - CLM gathers activity data through: - Direct integrations with individual SaaS APIs. - Google Workspace SAML audit logs for indirect integrations. - Employee activity is stored per application in an Amazon RDS-backed PostgreSQL database. - Employees receive email and Slack notifications after a configurable period of inactivity, with 90 days as the default. - Notifications explain the specific login or application action required to remain active. - If the employee does not respond after multiple reminders, CLM deactivates the account automatically. - Employees can reopen access by submitting a Freshservice ticket. - Accounts are restored within seconds, including their previous roles and permissions. ## Microservice Architecture - CLM consists of Python microservices running on AWS Lambda. - The services share a central PostgreSQL database. - Microservices provide: - Easier scaling as Datadog adds more SaaS applications. - Greater resilience and flexibility. - A modular foundation for future development. - The architecture introduced complexity because services required different APIs and libraries with overlapping functionality. ## Application-Specific Adapters - Each SaaS product is represented by an adapter shared across CLM microservices. - Adapters isolate application-specific API logic from the core workflows. - A typical adapter supports operations such as: - Retrieving users. - Fetching login activity. - Activating and deactivating accounts. - Onboarding and offboarding users. - This design provides: - Clear separation of responsibilities. - Reusable and flexible integration code. - Simpler microservices that do not need to handle each application’s unique behavior. CLM demonstrates how automated usage monitoring can simultaneously improve SaaS security, reduce unnecessary spending, and minimize disruption for employees. A modular adapter-based architecture is particularly useful when managing a growing portfolio of third-party applications.

Read original(opens in new tab)
datadog3 min readCurated summary

It's always DNS . . . except when it's not: A deep dive through gRPC, Kubernetes, and AWS networking

A routine update to a critical metrics query service caused intermittent errors and increased latency. Although logs initially pointed to DNS failures, the investigation revealed a deeper networking problem involving dropped packets and saturated AWS VPC connection tracking. The incident highlighted how Kubernetes, Cilium, AWS networking, and DNS behavior can interact in ways that obscure the true cause. ## Initial Symptoms and Apparent DNS Failures - Errors increased whenever the metrics query service was rolled out. - The service retrieves data from metric stores for dashboards and monitor evaluations. - Automatic retries reduced user-facing failures but increased latency. - Service logs showed DNS errors when connecting to dependencies inside Kubernetes. - The investigation therefore began with the cluster’s DNS infrastructure. ## NodeLocal DNSCache Reaches Its Limits - NodeLocal DNSCache runs as a `node-local-dns` DaemonSet on every Kubernetes node. - DNS pods had: - A 64 MB memory limit - A `max_concurrent` limit of 1,000 requests - The pods experienced out-of-memory errors and rejected requests during rollouts. - Increasing memory to 256 MB stopped the OOM errors, but DNS failures continued. - Request volume was far below the expected capacity: - Normally about 400 queries per second - Nearly 2,000 queries per second during rollouts - Expected capacity of at least 200,000 queries per second - Upstream resolvers were marked unhealthy, suggesting that NodeLocal DNSCache could not establish or maintain connections. - Because upstream requests could wait up to five seconds, connection failures consumed concurrency slots and made the cache appear overloaded. ## Evidence of a Network Problem - The instances were below their 5-Gbps sustained throughput limits. - TCP retransmits increased in correlation with service rollouts. - Engineers suspected brief traffic spikes, or microbursts, that were not visible in aggregate throughput metrics. - This shifted the investigation from DNS configuration toward lower-level AWS networking behavior. ## AWS VPC Connection Tracking - ENA metrics revealed a significant increase in `conntrack_allowance_exceeded`. - This metric counts packets dropped when VPC connection tracking becomes saturated. - Connection tracking maintains state for network flows and supports features such as stateful EC2 security groups. - The infrastructure used two tracking layers: - VPC conntrack maintained at the hypervisor level - Linux conntrack inside each instance - VPC conntrack appeared saturated even though Linux conntrack contained fewer than 60,000 entries—well within the observed capacity of similar instances. - AWS Support confirmed that conntrack capacity varies by instance type and that VPC conntrack limits could differ substantially from Linux conntrack limits. - Scaling to larger instances resolved the symptoms, but the engineers wanted to understand the traffic pattern and find a more efficient long-term solution. ## VPC Flow Logs as the Next Investigation Tool - The team turned to Amazon VPC Flow Logs to examine the service’s low-level network behavior. - These logs were expected to clarify why connection tracking filled up and how rollout traffic contributed to the saturation. - The investigation was still ongoing at the point where the provided article excerpt ends.

Read original(opens in new tab)
datadog3 min readCurated summary

How Datadog uses Datadog to gain visibility into the Datadog user experience

Datadog’s product designers use their own monitoring tools to supplement interviews with quantitative insight into user behavior. By applying Real User Monitoring (RUM) and Logs to design questions, they made decisions about fonts, component functionality, and time-range input based on actual usage. This “dogfooding” approach improved products while making design collaboration faster and more evidence-based. ## Choosing a Monospace Font - Datadog uses monospace text for logs, stack traces, source code, container IDs, and dense data views. - Previously, users received different system fonts through a generic font stack, including Consolas, Menlo, and Courier. - The team used the browser’s CSS Font Loading API and RUM to determine which fonts users were actually seeing. - They analyzed the results in RUM Analytics and shared them through a dashboard with designers and engineers. - Datadog selected **Roboto Mono** as the standard font and used RUM after launch to verify that the rollout worked as intended. - Matching the existing visual proportions was important because font-size and character-width changes could disrupt tightly designed tables and other interfaces. ## Simplifying the DraggablePane Component - DraggablePane lets users resize adjacent content panels, but its small handle contained several controls that created visual clutter. - Custom loggers were added to the component and its draggable handle to track how users interacted with each feature. - Logs showed that almost no users used the minimize and maximize buttons, despite the space they occupied. - The team removed those buttons and replaced their functionality with a double-click on the handle. - Datadog notes that custom actions in RUM now provide a more direct way to collect this kind of interaction data. ## Expanding Custom Time-Range Syntax - Datadog initially offered only preset ranges such as 15 minutes, 1 hour, and 1 day. - The DateRangePicker introduced text-based custom ranges, but early versions supported only limited patterns such as “{N} months” or explicit dates. - Logs captured invalid user-entered time expressions, along with the page and country associated with each request. - The most common unsupported input involved “weeks,” including phrases like “last 1 week” and “last 2 weeks.” - The team used these patterns to prioritize improvements to the parser. - After adding support for common previously invalid inputs, the error rate fell from roughly 10 percent to 5–6 percent. ## Dogfooding and Collaboration - Designers tracked behavior, analyzed results, built dashboards, and documented findings using Datadog products. - Keeping data collection, analysis, and presentation in one platform made design reviews more efficient. - Shared dashboards and documentation helped designers and engineers collaborate around concrete evidence rather than assumptions. - Using the product internally also gave the team direct experience with the platform from a user’s perspective. Datadog’s examples show that quantitative product data works best alongside qualitative research: interviews explain user needs, while RUM and Logs reveal how often behaviors occur and which improvements will have the greatest impact.

Read original(opens in new tab)
datadogOriginal article

How Datadog uses Datadog to gain visibility into the Datadog user experience | Datadog (opens in new tab)

Datadog leverages its own monitoring tools to bridge the gap between qualitative user interviews and quantitative performance data. By "dogfooding" features like Real User Monitoring (RUM) and Logs, the product design team makes evidence-based UI/UX adjustments while gaining firsthand empathy for the user experience. This approach allows them to identify exactly how users interact with specific components and where current designs fail to meet user expectations. **Optimizing Font Consistency via CSS API Tracking** * To ensure visual precision in information-dense views like the Log Explorer, the team needed to transition from a generic system font stack to a standardized monospace font. * Designers used the Web API’s `Document.font` interface and the CSS Font Loading API via Datadog RUM to collect data on which specific fonts were actually being rendered on users' machines. * By analyzing a dashboard of these results, the team selected Roboto Mono as the standard, ensuring the new font’s optical size matched what the plurality of users were already seeing to avoid breaking embedded tables. **Simplifying Components through Interaction Logging** * The `DraggablePane` component, used for resizing adjacent panels, was suffering from UI clutter due to physical buttons for minimizing and maximizing content. * The team implemented custom loggers within Datadog Logs to track how frequently users clicked these specific controls versus interacting with the draggable handle. * The data revealed that the buttons were almost never used; consequently, the team removed them and replaced the functionality with a double-click event, significantly streamlining the interface. **Refining Syntax Support through Error Analysis** * When introducing the `DateRangePicker` for custom time frames, the team needed to expand the component's logic to support natural language strings. * By aggregating "invalid inputs" in Datadog Logs, the team could see the exact strings users were typing—such as "last 2 weeks"—that the system failed to parse. * Analyzing these common patterns allowed the team to update the parsing logic for high-demand keywords, which resulted in the component’s error rate dropping from 10 percent to approximately 5 percent. Leveraging internal monitoring tools allows design teams to move beyond guesswork and create highly functional interfaces. For organizations managing complex technical products, tracking specific component failures and interaction frequencies is an essential strategy for prioritizing the design roadmap and improving user retention.

datadogOriginal article

Our journey taking Kubernetes state metrics to the next level | Datadog (opens in new tab)

Datadog’s container observability team significantly improved the performance of kube-state-metrics (KSM) by contributing core architectural enhancements to the upstream open-source project. Faced with scalability bottlenecks where metrics collection for large clusters took tens of seconds and generated massive data payloads, they revamped the underlying library to achieve a 15x improvement in processing duration. These contributions allowed for high-granularity monitoring at scale, ensuring that the Datadog Agent can efficiently handle millions of metrics across thousands of Kubernetes nodes. ### Challenges with KSM Scalability * KSM uses the informer pattern to expose cluster-level metadata via the Openmetrics format, but the volume of data grows exponentially with cluster size. * In high-scale environments, a single node generates approximately nine metrics, while a single pod can generate up to 40 metrics. * In clusters with thousands of nodes and tens of thousands of pods, the `/metrics` endpoint produced payloads weighing tens of megabytes. * The time required to crawl these metrics often exceeded 15 seconds, forcing administrators to reduce check frequency and sacrifice real-time data granularity. ### Limitations of Legacy Implementations * KSM v1 relied on a monolithic loop that instantiated a Builder to track resources via stores, but it lacked efficient hooks for metric generation. * The original Python-based Datadog Agent check struggled with the "data dump" approach of KSM, where all metrics were processed at once during query time. * To manage the load, Datadog was forced to split KSM into multiple deployments based on resource types (e.g., separate deployments for pods, nodes, and secondary resources like services or deployments). * This fragmentation made the infrastructure more complex to manage and did not solve the fundamental issue of inefficient metric serialization. ### Architectural Improvements in KSM v2.0 * Datadog collaborated with the upstream community during the development of KSM v2.0 to introduce a more extensible design. * The team focused on improving the Builder and metric generation hooks to prevent the system from dumping the entire dataset at query time. * By moving away from the restrictive v1 library structure, they enabled more efficient reconciliation of metric names and metadata joins. * The resulting 15x performance gain allows the Datadog Agent to reconcile labels and tags—such as joining deployment labels to specific metrics—without the significant latency overhead previously experienced. Contributing back to the open-source community proved more effective than maintaining internal forks for scaling Kubernetes infrastructure. Organizations running high-density clusters should prioritize upgrading to KSM v2.0 and optimizing their agent configurations to leverage these architectural improvements for better observability performance.

datadog3 min readCurated summary

Our journey taking Kubernetes state metrics to the next level

Datadog contributed major scalability improvements to kube-state-metrics (KSM), after discovering that its metric collection process struggled with very large Kubernetes clusters. Millions of metrics could require tens of megabytes and tens of seconds to process every 15 seconds, forcing Datadog to reduce collection frequency. Their redesign improved collection duration by 15x and enabled more granular monitoring at scale. ## Datadog’s Kubernetes Observability Role - The Datadog Containers team monitors Kubernetes infrastructure and ensures reliable collection of: - Logs - Traces - Custom metrics - Profiles - Security signals - KSM is central to Datadog products such as Kubernetes metrics integration and Orchestrator Explorer. ## How Kubernetes State Metrics Works - KSM uses Kubernetes informers to watch objects registered with the API server. - Enabled collectors monitor resources such as pods, nodes, deployments, and services. - It generates lifecycle and metadata metrics in text-based OpenMetrics format. - Users can restrict monitored resources through the `resources` flag. - The Datadog Agent’s KSM check: - Runs every 15 seconds. - Discovers KSM containers. - Crawls their `/metrics` endpoint. - Reconciles metric metadata and applies configured label joins. - Label joins allow metadata from one metric, such as a deployment label, to become a tag on other metrics for the same object. ## Scaling Challenges - Datadog found that KSM needed to be split across multiple deployments beyond a few hundred nodes and thousands of pods. - Their deployments divided collectors by resource type: - Pods - Nodes - Services, deployments, jobs, persistent volumes, and other resources - Metric volume varied substantially: - Endpoints, jobs, and deployments produced roughly five metrics per object. - Nodes produced around nine metrics each. - Pods produced around 40 metrics each. - Large clusters with thousands of nodes and tens of thousands of pods could generate millions of metrics per scrape. - Crawling the metrics endpoint could take tens of seconds and transfer tens of megabytes. - Datadog had to reduce check frequency, sacrificing metric granularity and user experience. ## KSM’s Original Architecture - KSM v1 relied on a central loop that created a Builder and managed resource stores. - Each store used informers to track a particular Kubernetes resource. - For example, an HPA store maintained the list-and-watch logic for HorizontalPodAutoscalers. - The Builder generated metrics from the tracked resources. - Datadog identified two limitations: - Too much data was emitted and processed at query time. - The Builder did not provide a suitable extension point for custom metric-generation logic. ## Contributing the Redesign Upstream - As the KSM community prepared version 2.0 in early 2020, Datadog saw an opportunity to address its scalability and extensibility problems in the upstream project. - Rather than maintaining a private solution, the team contributed its findings and improvements to the open-source community. - The resulting work reportedly reduced metric collection duration by 15x, making high-scale, more frequent collection practical. Datadog’s experience shows that upstream open-source collaboration can solve internal infrastructure bottlenecks while improving the project for the broader Kubernetes community.

Read original(opens in new tab)
datadog2 min readCurated summary

How we optimized our Akka application using Datadog’s Continuous Profiler

Datadog discovered that an unexpected 20–30% CPU overhead came from Akka’s use of `ForkJoinPool`, not from the log-processing code they initially suspected. Profiling showed that an actor handling intermittent latency metrics repeatedly caused worker threads to park and unpark. Moving that actor to a busier, more stable dispatcher reduced CPU usage by about 30%. ## How Profiling Revealed the Problem - Datadog used Akka to parallelize log-event processing through actors and dispatchers. - An optimization to log parsing produced little improvement, despite reducing parsing CPU time. - Continuous Profiler flame graphs showed increased CPU time in: - `ForkJoinPool.scan()` - `Unsafe.park()` - Thread-level analysis revealed that the default Akka dispatcher—not the expected dedicated work pool—was responsible. - Many of the affected threads were executing a latency-reporting actor. ## Why `ForkJoinPool` Was Consuming CPU - `ForkJoinPool` dynamically manages worker threads: - It creates threads when work increases. - It suspends idle threads with `Unsafe.park()`. - It resumes them with `Unsafe.unpark()`. - It terminates idle workers after a default period. - The latency actor received a few hundred events per second, processed them within milliseconds, and then remained idle until the next batch. - Because the pool allowed up to 32 threads—matching the number of processor cores—it repeatedly activated and suspended many workers. - These frequent parking and unparking operations created short CPU spikes and excessive time in `ForkJoinPool.scan()`. ## The Dispatcher Change - The team moved the latency actor from Akka’s default dispatcher to the main `work-dispatcher`. - The work dispatcher already handled a steadier stream of log-processing tasks, keeping its worker threads active. - This required only a configuration change assigning the actor to `work-dispatcher`. - CPU usage fell by roughly 30% across services. - The default dispatcher also shrank from 32 threads to 2, confirming that unnecessary thread activation was the cause. ## Recommendations - Monitor CPU time spent in `ForkJoinPool.scan()`, especially when it exceeds roughly 10–15%. - Limit the number of Akka actor instances. - Set a suitable maximum thread count for each pool. - Reduce the number of separate thread pools where practical. - Use task queues to absorb frequent, short-lived workload spikes. - Aim to keep the number of active `ForkJoinPool` workers relatively stable and avoid repeated parking and unparking.

Read original(opens in new tab)
datadog2 min readCurated summary

How Datadog's IT team automated monitoring third-party accounts

Datadog built “Clarity,” an automated system for auditing SaaS accounts against Workday’s employee records. It regularly identifies accounts that do not belong to active employees, then logs, tickets, stores, and communicates findings through Datadog, Freshservice, Slack, and DynamoDB. The system replaces infrequent, manual reviews with continuous visibility and faster remediation of security and cost risks. ## The Need for Automated SaaS Audits - Modern companies rely on dozens or hundreds of external applications. - Manual account reviews are difficult to scale and may fail to detect unauthorized or abandoned accounts promptly. - An unexpected account in an identity provider or SaaS application could give a bad actor access to sensitive systems. - Datadog needed recurring audits as its SaaS portfolio continued to expand. ## Clarity’s Requirements - Use a single source of truth for employee status: - Datadog uses Workday. - Other organizations could use Okta, OneLogin, ADP, or Active Directory. - Run frequently enough to provide timely visibility. - Support manual execution when needed. - Integrate with existing communication, ticketing, and observability tools, such as Slack, Freshservice, and Datadog. - Minimize disruption to IT workflows and encourage adoption across a globally distributed organization. ## Audit Pipeline - A CloudWatch Event Rule triggers the audit Monday through Friday at 10 a.m. EST. - Clarity concurrently retrieves: - Active employees from Workday. - Active users from primary SaaS applications such as Slack, GitHub, and Zoom. - It compares SaaS user email addresses with active employee records. - Accounts without a matching active employee are flagged. - Results are: - Sent to Datadog as logs and metrics. - Added to DynamoDB for historical tracking. - Converted into Freshservice tickets. - Reported through Slack notifications with an audit summary. ## Datadog Metrics and Investigation - Clarity sends a metric for every flagged account using the Datadog Metrics API and Python SDK. - It uses a gauge metric to track flagged accounts over time. - Metrics include tags such as: - Environment, such as production. - Responsible team. - SaaS service. - Flagged user’s email address. - These tags provide the context needed to investigate the account and support alerting and visualization within Datadog. ## Practical Outcome Clarity provides a repeatable, automated control for SaaS account governance. Organizations implementing a similar system should connect an authoritative employee directory to their SaaS inventory, run audits regularly, and integrate findings with their existing monitoring, ticketing, and notification workflows.

Read original(opens in new tab)
datadog3 min readCurated summary

How we minimized the overhead of Kubernetes in our job system

Kubernetes can improve machine management and scalability, but its scheduling and runtime overhead can significantly reduce job throughput if configured poorly. Datadog found its Kubernetes-based job system used more CPU and completed jobs 40–50% more slowly than the previous VM-based system. By designing a controlled experiment, choosing better metrics, and tuning pod resource requests, the team recovered performance to roughly VM parity while investigating the overhead of running one parent process per pod. ## Designing a Comparable Experiment - The initial comparison was difficult because the Kubernetes and VM deployments differed in: - Number of nodes - Number of worker-parent clusters - Workload and enqueue rate - A controlled experiment was created using: - Identical `c5.2xlarge` machines - The same kernel version, `3.13.0-141` - Both systems repeatedly running a simple Python job - Each Kubernetes pod contained one parent process and its worker processes, making pod count equivalent to parent-process count per node. - The older kernel did not include CPU mitigations, avoiding that variable in the comparison. ## Choosing Useful Performance Metrics ### Measuring node effort - Load average initially appeared useful for measuring machine utilization. - Kubernetes background processes—such as cluster polling and pod-state checks—artificially increased load average. - Load average counts runnable processes rather than the amount of CPU time they actually consume. - The team therefore used CPU idle time instead: - It measures unused CPU capacity. - It reflects actual CPU work rather than the number of active processes. ### Measuring system performance - The job system optimized for throughput rather than latency. - Throughput was measured by the number of jobs completed within 30 seconds. - Latency remained useful for detecting queueing problems, but throughput was the primary success metric. ## Tuning Kubernetes Resource Requests - The main performance gains came from improving pod scheduling. - The target was six pods per `c5.2xlarge` node. - Initially, each pod requested: - One full CPU core - More memory than necessary - Since the node had eight cores and approximately 1.5 GiB of memory consumed by Kubernetes and system services, only four pods could be scheduled. - Requests were reduced to: - `100m` CPU, or 100 millicores - `500 MB` memory - CPU tuning generally enabled six pods per node, although some nodes still scheduled only five. - Further memory reduction was needed because system daemons consumed enough memory to prevent six pods from fitting on some nodes. - Resource requests affect scheduling minimums, while limits constrain containers after they start. - These request changes did not slow jobs because the pods still received sufficient resources to operate. ## One Parent Process per Pod - The team considered placing multiple parent processes in each pod to reduce potential pod overhead. - One parent plus its workers was a natural application unit and simplified orchestration. - The decision depended on how much overhead each pod introduced: - High overhead would favor fewer, larger pods. - Low overhead would favor one parent per pod for simpler management. - Using `pstree`, the team identified six job-system instances per node and traced their process trees through components such as: - `containerd-shim` - `tini` - The application process - They estimated that each pod included overhead associated with three containers, particularly `containerd-shim`. - CPU overhead was then investigated using `perf sched`. The practical lesson is to compare equivalent workloads, measure actual CPU consumption rather than relying blindly on load average, and tune Kubernetes requests for the desired packing density. Resource requests should be large enough for reliable operation but not so large that they unnecessarily prevent pods from being scheduled together.

Read original(opens in new tab)
datadog3 min readCurated summary

Engineering spotlight: Maël Nison

Maël Nison’s journey from learning DarkBASIC on La Réunion and in Toulouse to becoming Yarn’s principal maintainer illustrates how curiosity, open source, and a focus on solving practical problems can shape a career. His early experimentation with games, websites, forums, and content-management systems developed into a lasting interest in improving developer workflows. That path eventually led through EPITECH, startups, Facebook, and Datadog, while giving him broad experience across both software and community leadership. ## Early Programming on La Réunion and in Toulouse - Maël grew up on the remote Indian Ocean island of La Réunion, where he had little access to computers. - After moving to Toulouse, he discovered a school programming club and began creating games with DarkBASIC. - DarkBASIC simplified 2D and 3D Windows game development through built-in libraries, tutorials, and DirectX support. - Seeing code immediately produce something on screen made programming feel logical and compelling to him. - By high school, he was building PHP websites, working with SQL, and experimenting with multiple languages and platforms. ## Discovering Open Source and Workflow Automation - In the early 2000s, distributing software was much harder because platforms such as GitHub did not yet exist. - Maël shared source archives through online forums, reflecting the informal nature of early open source communities. - His interest in forum software led to work on content-management systems. - He focused on reducing repetitive administrative workflows, such as allowing users to edit content directly instead of navigating through multiple administration pages. - This pattern—identifying a problem, building a solution, and sharing it with others—became a central theme in his career. ## Education at EPITECH - Maël attended EPITECH in Paris, an institution centered on practical technical education and self-directed learning. - The school emphasized peer assessment and hands-on projects rather than traditional, theory-heavy instruction. - He also spent a year abroad in Québec. - During his final year, he combined his studies with his first full-time job, gaining professional experience before graduation. ## Joining Facebook and Yarn - In 2017, after several years in startups, Maël moved from France to London seeking opportunities at larger organizations. - He joined Facebook without specifically intending to work on a package manager. - Facebook’s onboarding “boot camp” identified his skills and connected him with the emerging Yarn project. - He welcomed the opportunity to work on open source during his regular working hours. - What began as a few pull requests became a multi-year role as a major maintainer and leader of the project. ## Yarn’s Technical and Community Evolution - Yarn was rewritten in TypeScript and re-architected into a more modular system. - It evolved from an internal Facebook tool into a genuinely community-driven open source project. - Maël’s responsibilities expanded far beyond coding: - Product management and roadmap planning - Team leadership and infrastructure - Customer support and community work - Web design, evangelism, and outreach - Defining the project’s broader vision - Although he left Facebook for Datadog in 2019, he continued leading Yarn while taking on new challenges at Datadog. Maël’s experience suggests that careers can grow from small, self-directed experiments into major technical leadership opportunities. Developers can follow a similar path by solving concrete problems, sharing their work openly, and being willing to take on the technical, organizational, and community responsibilities that accompany successful projects.

Read original(opens in new tab)
datadog3 min readCurated summary

PHP 8: Observability baked right in

PHP’s observability mechanisms failed to keep pace with Zend Engine improvements in PHP 7 and PHP 8, especially the introduction of JIT. Existing hooks imposed significant runtime costs, created compatibility and stability problems, and limited tracers such as Datadog’s ability to evolve. PHP 8 addressed these issues by introducing a new observer API designed specifically for modern, lower-overhead runtime instrumentation. ## Observability Before PHP 8 ### The `zend_execute_ex` VM Hook - Extensions could override `zend_execute_ex` to intercept every PHP-defined function and method call. - This moved PHP calls onto the native C stack, whose limited size (`ulimit -s`) could cause stack overflows and process crashes. - Every userland call was intercepted, even when an extension only needed to observe a subset, adding overhead to call-heavy applications. - The compiler could no longer use optimized distinctions between userland and internal calls, such as `DO_UCALL` and `DO_ICALL`. - Extensions had to manually forward the hook to other extensions, creating “noisy neighbor” problems, unexpected behavior, and possible crashes. - The hook was incompatible with PHP 8’s JIT compiler. ### Custom Opcode Handlers - Extensions could replace handlers for function-call opcodes, avoiding the native-stack problem associated with `zend_execute_ex`. - These handlers still required careful forwarding to neighboring extensions, which was historically unreliable. - Handlers could mutate VM state—for example, preventing the original opcode from running—making reliable cooperation between multiple extensions impossible in some cases. - Generators could not be fully instrumented through custom opcode handlers. - Like `zend_execute_ex`, custom opcode handlers were incompatible with the PHP 8 JIT. ### Zend Extension Hooks - Zend Extensions had privileged access to engine-level function-call begin and end handlers. - This approach caused the compiler to emit `EXT_FCALL_BEGIN` and `EXT_FCALL_END` around every function call. - The additional opcodes introduced too much overhead for production-grade tracing. ### AST Injection Experiments - Researchers explored injecting observability nodes into the abstract syntax tree during compilation. - These nodes could invoke tracing functions before and after calls. - However, injecting instrumentation around every function call was expected to have overhead comparable to Zend Extension hooks. - No production-ready tracers using this approach were known at the time. ## The Need for a New Observer API - Existing hooks forced observability tools to interfere deeply with VM execution or compiler output. - Their limitations included excessive overhead, stack-safety risks, incomplete generator support, extension conflicts, and JIT incompatibility. - These constraints prevented tools such as the Datadog PHP tracer from taking full advantage of PHP 8. - In response, the authors and the PHP internals community developed and shipped the observer API in PHP 8, providing a foundation for more modern and efficient tracing, profiling, and debugging. PHP 8’s observer API was necessary because older instrumentation techniques were either unsafe, too slow for production, difficult to compose, or incompatible with the JIT. A runtime-level observability mechanism designed alongside the engine is a more sustainable approach than modifying VM hooks, opcodes, or compiled syntax from extensions.

Read original(opens in new tab)
datadog3 min readCurated summary

Introducing Glommio, a thread-per-core crate for Rust and Linux

Thread-per-core architecture can significantly improve performance and reduce cloud costs by avoiding lock contention and expensive context switches. However, adopting it directly can reduce developer productivity because it requires new programming patterns and careful data ownership. Datadog developed Glommio, a Rust framework intended to make thread-per-core applications easier to build and maintain. ## Why Traditional Threading Has Limits - Applications commonly use multiple threads to perform independent tasks in parallel. - Shared data requires locks, which introduce contention and waiting. - Thread context switches can cost around five microseconds—potentially more than modern storage I/O operations using technologies such as `io_uring`. - Asynchronous programming reduces blocking, but many runtimes still rely on thread pools or separate worker threads for operations such as file I/O. ## How Thread-per-Core Works - Each CPU core runs a single application thread, often pinned to that core. - Because the operating system does not move the thread between cores, ordinary thread context switches are eliminated. - Hardware interrupts and auxiliary tasks can still interrupt execution. - For maximum performance, operators may reserve certain CPUs for interrupts and system services rather than application work. ## Sharding Data Across Cores - Thread-per-core applications depend on sharding: each thread owns a distinct subset of the data or requests. - Examples include assigning Kafka partitions or database key ranges to individual threads. - Requests assigned to one thread execute there to completion unless the code explicitly yields. - This ownership model prevents multiple threads from handling the same request or data simultaneously. ## Eliminating Locks - Since one thread processes a shard at a time, operations on that shard are naturally serialized. - A conventional threaded cache requires locks because multiple threads may update the same data concurrently. - Sharding reduces contention by dividing a large cache into smaller sections, but locks may still be needed if the operating system switches between threads. - With thread-per-core, updates to keys in the same shard occur sequentially, so an update can complete without acquiring a lock. ## Glommio and Existing Precedents - Thread-per-core is not a new concept; the author previously worked with Seastar, a C++ framework used by ScyllaDB. - Datadog’s Glommio brings the model to Rust while aiming to make its programming challenges more manageable. - The framework is motivated by the need to preserve developer productivity while achieving the efficiency gains of thread-per-core systems. Thread-per-core is most suitable for highly parallel, high-throughput workloads with naturally shardable data. Its performance benefits depend on disciplined data ownership and cooperative execution, while frameworks such as Glommio can reduce the complexity of adopting the model.

Read original(opens in new tab)
datadog3 min readCurated summary

The Old Datadog and the Sea

Wouter de Bie describes upgrading his 1992 Hunter Legend sailboat, *Second Wind*, into a connected, data-driven vessel. His goals were to unify onboard instruments, improve safety with vessel tracking, add accurate wind measurements, and collect data for later analysis. The central solution was an NMEA 2000 network, which allowed compatible devices to share data and power over a single backbone. ## Building a Unified Instrument Network - The boat originally had a depth sounder, speedometer, autopilot, chartplotter, and GPS, but the systems were not centrally connected. - The existing Raymarine equipment used SeatalkNG, which is compatible with NMEA 2000 despite having different cables and connectors. - The older speed and depth displays used NMEA 0183 rather than NMEA 2000. - Instead of adding protocol converters, Wouter replaced the older displays with new NMEA 2000-compatible instruments. - Once connected to the backbone, speed and depth data appeared on the chartplotter. ## Why NMEA 2000 Was Chosen - NMEA 2000 is similar to the CAN bus used in automobiles. - Devices connect to a shared backbone and broadcast small data messages for other equipment to consume. - The network operates at 250 kbit/s, which is sufficient for marine instruments. - Its cables carry both power and data, reducing wiring complexity. - Most marine electronics vendors support the standard. ## Improving Safety with AIS - Wouter added an Automatic Identification System (AIS) transponder to detect nearby vessels. - AIS broadcasts a vessel’s name, identifier, speed, heading, and coordinates over VHF radio. - The system only detects AIS-equipped vessels within line of sight, but offers a lower-cost alternative to radar. - After installing the transponder and routing its antenna cable to the stern, nearby ships appeared on the chartplotter. - The transponder’s built-in GPS also supplied positioning data to the NMEA 2000 network. ## Adding Wind Measurements - The original wind indicator was only an analog vane, requiring Wouter to look up at the mast and providing no wind-speed measurement. - He purchased a NMEA 2000 wind transducer and cockpit display. - The transducer measures wind angle with a vane and wind speed with a rotor, typically from the top of the mast. - Installation required routing a cable through the mast and boat. - A friend was hoisted up the mast on a calm evening to drill the mounting hole and install the sensor. The project demonstrates how replacing incompatible legacy instruments and connecting modern devices through NMEA 2000 can turn a boat into an integrated safety and analytics platform. Once all sensor data is centralized, it can support both better sailing decisions and longer-term analysis of performance and conditions.

Read original(opens in new tab)
datadog3 min readCurated summary

Secure publication of Datadog Agent integrations with TUF and in-toto

Datadog built a compromise-resilient CI/CD system to publish Agent integrations independently of full Agent releases. It combines in-toto for end-to-end supply-chain verification with TUF for secure key and metadata distribution. Together, these technologies ensure that users install only integrations derived from developer-approved source code, even if parts of the infrastructure are compromised. ## Independent Integration Publishing - Agent integrations were traditionally bundled into full Agent releases. - This delayed important integration updates and prevented users from trying new integrations immediately. - Datadog wanted automation to build and publish integrations on demand without fully trusting the automation itself. ## End-to-End Verification with in-toto - TLS and GPG package signatures help prevent man-in-the-middle attacks but do not protect against compromised build or publishing infrastructure. - in-toto defines the software supply chain as a fixed sequence of signed steps. - Each step records the inputs it received and the outputs it produced, allowing the Agent to verify that only authorized parties performed the required work. - The integration pipeline includes: - Developers signing Python and YAML source files. - CI/CD packaging the source into Python wheels without modifying existing wheels. - A signing step applying TUF signatures to the wheels. - The Datadog Agent verifying that the downloaded wheel matches the developer-signed source. ## Secure Distribution with TUF - in-toto does not itself provide a secure way to distribute, revoke, or replace verification keys. - TUF supplies signed, compromise-resilient metadata for: - The root of trust for wheels and supply-chain metadata. - The in-toto-defined workflow. - Public keys used to verify the workflow. - TUF protects against tampering, rollback attacks, and indefinite replay of outdated metadata. - Offline trust bootstrapping and protected developer keys are essential to the overall security model. ## Hardware-Protected Developer Signing - Developers use Yubikeys to generate and store GPG signing keys. - Private keys cannot be exported from the device, assuming correct firmware. - Signing requires both a secret PIN and physical interaction with the Yubikey. - A command-line tool integrates in-toto and GPG, preserving a convenient developer workflow while reducing key-compromise risk. ## Transparent Verification for Users - The Datadog Agent automatically invokes TUF and in-toto when downloading or updating integrations. - Users need no workflow changes under normal conditions. - If metadata, signatures, or supply-chain steps fail verification, installation is blocked and the Agent reports the failure. Datadog’s approach demonstrates that secure automated publishing requires layered controls: in-toto verifies how software was produced, while TUF securely manages the trust and distribution mechanisms needed to validate it.

Read original(opens in new tab)