CubeAPM
CubeAPM CubeAPM

Monitoring a Fastify Application: Datadog Setup, Overhead, and Alternatives

Monitoring a Fastify Application: Datadog Setup, Overhead, and Alternatives

Table of Contents

Fastify has earned its place among Node.js frameworks by delivering throughput 2 to 3 times higher than Express in production benchmarks. But without proper observability, even the fastest framework can degrade silently as teams add features, scale traffic, and connect new dependencies.

This guide walks through monitoring a Fastify application using Datadog’s APM agent, covering installation, instrumentation, performance overhead, and cost implications. It also compares five alternatives ranging from open source platforms to managed on-premises solutions evaluated on pricing, OpenTelemetry compatibility, and deployment model.

Prerequisites

Before instrumenting Fastify for monitoring, ensure you have the following:

  • Node.js 18 or later installed
  • A running Fastify application in development or production
  • Access to modify application startup code and environment variables
  • Datadog account with API key (for Datadog setup) or alternative monitoring platform credentials
  • Basic understanding of distributed tracing concepts
  • PostgreSQL or another database if following along with database query tracing examples

Step 1: Install and Initialize the Datadog APM Agent

Datadog APM for Node.js works by automatically instrumenting common libraries including Fastify, HTTP, database drivers, and external API clients. The agent must be initialized before any other code in your application to ensure all modules are patched correctly.

Install the Datadog tracing library:

npm install dd-trace --save

Create an instrumentation file that loads before your application starts. This ensures the agent patches all HTTP and framework modules early.

// instrumentation.js
const tracer = require('dd-trace').init({
  service: 'fastify-api',
  env: process.env.NODE_ENV || 'development',
  version: process.env.APP_VERSION || '1.0.0',
  logInjection: true,
  runtimeMetrics: true,
  profiling: true
});
module.exports = tracer;

Update your application entry point to require this file first:

// server.js
require('./instrumentation');
const fastify = require('fastify')({ logger: true });
fastify.get('/health', async (request, reply) => {
  return { status: 'ok' };
});
const start = async () => {
  try {
    await fastify.listen({ port: 3000, host: '0.0.0.0' });
    console.log('Server running on port 3000');
  } catch (err) {
    fastify.log.error(err);
    process.exit(1);
  }
};
start();

Set the required environment variables:

export DD_AGENT_HOST=localhost
export DD_TRACE_AGENT_PORT=8126
export DD_SERVICE=fastify-api
export DD_ENV=production

If running the Datadog agent in a container, replace localhost with the agent container hostname.

Step 2: Install and Configure the Datadog Agent

The Datadog APM agent running inside your application sends trace data to a separate Datadog Agent process, which then forwards telemetry to Datadog’s backend. This agent must be installed on the same host or accessible over the network.

For local development using Docker:

docker run -d \
  --name datadog-agent \
  -e DD_API_KEY=your_api_key_here \
  -e DD_APM_ENABLED=true \
  -e DD_APM_NON_LOCAL_TRAFFIC=true \
  -p 8126:8126 \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  -v /proc/:/host/proc/:ro \
  -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro \
  datadog/agent:latest

For production deployments on Kubernetes, use the Datadog Helm chart or DaemonSet to ensure every node runs the agent. The agent collects traces from all pods on that node.

Verify the agent is receiving traces by checking the agent status:

docker exec datadog-agent agent status

Look for the APM section showing active trace connections and throughput.

Step 3: Instrument Database Queries and External API Calls

Datadog automatically instruments popular database drivers like pg for PostgreSQL, mysql2, and mongodb. No manual code changes are required for basic query tracing.

For custom spans or operations not automatically captured, use manual instrumentation:

const tracer = require('./instrumentation');
fastify.get('/users', async (request, reply) => {
  const span = tracer.startSpan('database.query.users');
  
  try {
    const result = await request.db.query('SELECT * FROM users WHERE active = true');
    span.setTag('db.row_count', result.rows.length);
    return result.rows;
  } catch (error) {
    span.setTag('error', true);
    span.setTag('error.message', error.message);
    throw error;
  } finally {
    span.finish();
  }
});

This creates a child span under the parent HTTP request trace, allowing you to see exactly how long the database query took and whether it succeeded.

For external HTTP calls, the agent instruments libraries like axios and node-fetch automatically. Each outbound request appears as a separate span in the trace view.

Step 4: Enable Log Correlation and Inject Trace Context

Datadog can correlate logs with traces by injecting trace and span IDs into every log line. This allows you to click from a slow trace directly to the relevant logs.

Enable log injection in the tracer configuration (already shown in Step 1):

const tracer = require('dd-trace').init({
  logInjection: true
});

Update your logger to output structured JSON that includes the injected fields:

const pino = require('pino');
const logger = pino({
  formatters: {
    log(object) {
      const span = tracer.scope().active();
      if (span) {
        object.dd = {
          trace_id: span.context().toTraceId(),
          span_id: span.context().toSpanId()
        };
      }
      return object;
    }
  }
});
fastify.addHook('onRequest', (request, reply, done) => {
  request.log = logger.child({ request_id: request.id });
  done();
});

Logs now include dd.trace_id and dd.span_id fields, which Datadog uses to link logs and traces in the UI.

Step 5: Configure Sampling and Retention

Datadog APM pricing is based on indexed spans and ingested spans separately. By default, Datadog samples 100% of traces at the agent level but only indexes a subset based on your retention filters.

To reduce costs while retaining full visibility into errors and slow requests, configure custom sampling rules:

const tracer = require('dd-trace').init({
  samplingRules: [
    { service: 'fastify-api', name: 'web.request', sample_rate: 1.0, max_per_second: 100 },
    { service: 'fastify-api', sample_rate: 0.1 }
  ]
});

This samples 100% of web requests up to 100 per second, then falls back to 10% sampling for all other spans. Errors and high latency requests are automatically prioritized for indexing regardless of sampling rate.

Step 6: Set Up Alerts for Latency and Error Rate

Create monitors in Datadog to alert when latency or error rates cross defined thresholds. Navigate to Monitors > New Monitor > APM and configure:

Latency alert example:

  • Metric: trace.web.request.duration.by.service
  • Condition: above 500ms for 5 minutes
  • Alert message: @slack-alerts Fastify API p95 latency exceeded 500ms

Error rate alert example:

  • Metric: trace.web.request.errors.by.service
  • Condition: above 5% for 3 minutes
  • Alert message: @pagerduty Fastify API error rate spiked above 5%

Route alerts to Slack, PagerDuty, email, or webhooks depending on severity. Configure separate alert thresholds for production and staging environments.

Understanding Datadog APM Overhead

Datadog’s APM agent adds measurable overhead to every traced request. The agent intercepts HTTP requests, wraps database queries, and serializes trace data before forwarding it to the Datadog Agent process.

Measured overhead in production Fastify applications:

  • Latency: 1 to 3 milliseconds added per traced request
  • CPU: 2% to 5% increase during peak traffic
  • Memory: 50MB to 150MB baseline agent memory footprint

The overhead increases with span count. A single HTTP request that makes 10 database queries and 3 external API calls will generate 14 spans, each requiring serialization and transmission. High span cardinality applications experience higher overhead.

To reduce overhead, disable tracing on high volume low value endpoints:

const tracer = require('dd-trace').init({
  plugins: false
});
tracer.use('http', {
  blocklist: ['/health', '/metrics', '/favicon.ico']
});

This prevents trace generation for endpoints that do not require observability.

Datadog APM Pricing for Fastify Applications

Datadog APM pricing has two dimensions: host-based infrastructure fees and indexed span retention fees. Both scale with traffic and configuration choices.

For a mid-sized Fastify deployment with 20 hosts, 10 million requests per month, and default retention:

  • APM host fee: $31 per host per month = $620
  • Indexed spans: ~500 million spans ingested, ~50 million indexed at $1.70 per million = $85
  • Total monthly cost: $705

Datadog pricing details are available on their pricing page.

Indexed span costs grow with traffic. A 10x traffic increase does not linearly increase costs if sampling is configured correctly, but it does increase ingested span volume and associated indexing fees.

The per-host fee includes 150GB of log ingestion. Additional logs cost $0.10 per GB ingested. If your Fastify application generates verbose logs, the combined APM and log cost can exceed $1,500 per month for a 20-host cluster.

This estimate models a specific workload profile with 20 hosts and 10 million requests per month. Actual costs vary based on span volume, retention settings, and log verbosity.

Troubleshooting Common Issues

Traces not appearing in Datadog UI

Verify the Datadog Agent is running and accessible from your application. Check the agent logs:

docker logs datadog-agent

Confirm the agent is receiving traces. If the agent shows zero APM connections, verify DD_AGENT_HOST and DD_TRACE_AGENT_PORT environment variables match the agent’s listening address.

High memory usage from dd-trace

Reduce the trace buffer size to lower memory footprint:

const tracer = require('dd-trace').init({
  flushInterval: 5000,
  sampleRate: 0.5
});

This flushes traces every 5 seconds instead of the default 10 seconds and samples 50% of requests, cutting memory usage in half.

Missing database query details

Ensure pg or your database driver is installed before dd-trace is initialized. The agent must patch the driver before it is required by your application code.

Spans missing for custom logic

Use manual instrumentation to create spans for operations not automatically captured:

const span = tracer.startSpan('custom.operation');
// perform work
span.finish();

Always call span.finish() in a finally block to prevent orphaned spans.

Alternatives to Datadog for Fastify Monitoring

Datadog APM works well for teams prioritizing managed SaaS and broad integrations. However, five alternatives offer different trade-offs on cost, deployment model, and OpenTelemetry compatibility.

CubeAPM

CubeAPM is a self-hosted observability platform designed for teams that want full control over telemetry data without managing open source infrastructure. It runs inside your VPC or on-premises and is compatible with OpenTelemetry, Datadog agents, and Prometheus.

Pricing: $0.15 per GB ingested, no per-host or per-user fees. For the same 20-host Fastify deployment ingesting 300GB of traces and logs per month, the cost is $45 per month.

OpenTelemetry support: Native. CubeAPM is built on OpenTelemetry from day one, meaning you can instrument Fastify with the OpenTelemetry Node SDK and send spans directly to CubeAPM without vendor lock-in.

Deployment: Self-hosted in your infrastructure. CubeAPM manages upgrades, patches, and support, but data never leaves your environment. This eliminates egress fees and ensures compliance with GDPR, HIPAA, and data residency requirements.

Best for: Teams with data sovereignty requirements, regulated industries, and engineering organizations that want predictable pricing without seat taxes or host-based billing.

SigNoz

SigNoz is an open source observability platform built on OpenTelemetry. It provides APM, logs, and infrastructure monitoring in a single stack with full control over data retention and storage.

Pricing: Free for self-hosted deployments. SigNoz Cloud starts at $49 per month for small teams and scales to $0.30 per GB for larger workloads.

OpenTelemetry support: Native. SigNoz only accepts OpenTelemetry data, ensuring no vendor lock-in.

Deployment: Self-hosted via Docker Compose, Kubernetes Helm chart, or SigNoz Cloud for managed deployment.

Best for: Teams that want open source control, are comfortable managing infrastructure, and prefer OpenTelemetry-first instrumentation.

Elastic APM

Elastic APM is part of the Elastic Stack and provides distributed tracing, metrics, and log correlation. It integrates tightly with Elasticsearch for indexing and Kibana for visualization.

Pricing: Free for self-hosted Elastic Stack. Elastic Cloud starts at $99 per month for standard deployments and scales based on data volume and retention.

OpenTelemetry support: Partial. Elastic APM agents use proprietary instrumentation but accept OpenTelemetry data via the Elastic APM server.

Deployment: Self-hosted or Elastic Cloud managed service.

Best for: Teams already running the ELK stack for logs and want to add APM without introducing a separate tool.

Honeycomb

Honeycomb is a SaaS observability platform optimized for high cardinality debugging. It excels at allowing engineers to query arbitrary fields across distributed traces without pre-defining indexes.

Pricing: Free tier with 20 million events per month. Pro plan starts at $130 per month and scales with event volume.

OpenTelemetry support: Native. Honeycomb recommends OpenTelemetry SDKs for all instrumentation.

Deployment: SaaS only. No on-premises option.

Best for: Teams debugging complex distributed systems with high cardinality data and variable query patterns.

Grafana Stack (Tempo + Loki + Prometheus)

The Grafana observability stack combines Tempo for traces, Loki for logs, and Prometheus for metrics. It offers a fully open source alternative to commercial APM platforms.

Pricing: Free for self-hosted. Grafana Cloud starts with a free tier and scales based on usage.

OpenTelemetry support: Strong. Tempo natively ingests OpenTelemetry traces, and Prometheus supports OpenTelemetry metrics.

Deployment: Self-hosted via Docker or Kubernetes, or Grafana Cloud for managed deployment.

Best for: Teams with existing Grafana dashboards, Prometheus monitoring, and the engineering capacity to manage a multi-component observability stack.

Conclusion

Monitoring Fastify applications with Datadog requires installing the APM agent, instrumenting database queries and external calls, and configuring sampling rules to control costs. The agent adds 1 to 3 milliseconds of latency per traced request and consumes 50MB to 150MB of memory, which is acceptable for most production workloads.

Datadog’s host-based pricing and indexed span fees make it expensive at scale, especially for high-traffic Fastify applications that generate millions of spans per day. Teams with data residency requirements or unpredictable traffic patterns may benefit from alternatives like CubeAPM, SigNoz, or the Grafana stack, which offer more control over data and pricing.

Choosing the right monitoring tool depends on your team’s priorities. If you prioritize managed SaaS with minimal operational overhead, Datadog or Honeycomb are strong choices. If you need data sovereignty, predictable costs, and full control, CubeAPM or SigNoz fit better. For teams already invested in the Elastic or Grafana ecosystems, extending those platforms to include APM avoids introducing new tooling.

Disclaimer: The information in this article reflects the latest details available at the time of publication and may change as technologies and products evolve. Features, pricing, and plan limits can change over time. Always verify the latest information directly with the vendor before making purchasing or deployment decisions.

Frequently Asked Questions

How much overhead does Datadog APM add to a Fastify application?

Datadog APM adds 1 to 3 milliseconds of latency per traced request and increases CPU usage by 2% to 5% during peak traffic. Memory footprint ranges from 50MB to 150MB depending on trace buffer size and span volume.

Can I use OpenTelemetry instead of the Datadog agent to monitor Fastify?

Yes. Fastify can be instrumented using the OpenTelemetry Node SDK, and traces can be exported to any OpenTelemetry-compatible backend including Datadog, SigNoz, Honeycomb, or CubeAPM. This avoids vendor lock-in.

What is the difference between ingested spans and indexed spans in Datadog pricing?

Ingested spans are all spans sent to Datadog from your application. Indexed spans are the subset retained for searching and analysis beyond 15 minutes. Datadog charges separately for both dimensions, which can lead to unexpected costs.

How do I reduce Datadog APM costs for a high-traffic Fastify application?

Configure sampling rules to trace 100% of errors and slow requests while sampling only 10% to 20% of normal traffic. Disable tracing on high volume low value endpoints like health checks. Use retention filters to control which spans are indexed long term.

Is CubeAPM compatible with Datadog agents?

Yes. CubeAPM accepts data from Datadog agents, OpenTelemetry SDKs, Prometheus exporters, and Elastic agents. You can switch to CubeAPM without changing your instrumentation code.

Which feature in Datadog helps trace requests across distributed systems?

Datadog APM’s distributed tracing feature propagates trace context across service boundaries, allowing you to follow a single request through multiple microservices, databases, and external APIs in a single flame graph view.

What type of tool is Datadog?

Datadog is a cloud-based observability platform that provides application performance monitoring, infrastructure monitoring, log management, real user monitoring, and synthetic monitoring in a single SaaS product.

×
×