← Back to blog

How to use Nuxt with newrelic node agent

nuxtvuejavascriptwebdevfrontend

The year is 2026, and our web applications are more sophisticated and distributed than ever. Nuxt, with its powerful full-stack capabilities, server-side rendering (SSR), and API routes powered by Nitro, has become a cornerstone for building modern, high-performance web experiences. But with great power comes great responsibility – the responsibility of ensuring your application is not just fast, but also reliable and observable.

In a world where microseconds count and every outage impacts user trust and revenue, robust application performance monitoring (APM) is non-negotiable. This is where tools like New Relic shine, offering deep insights into your application’s health, performance bottlenecks, and error rates. Today, we’re diving deep into how to integrate the New Relic Node.js agent with your Nuxt 3 (and beyond) applications, transforming your development and operations workflow.

The Critical Need for Observability in Modern Nuxt Apps

Nuxt 3 applications are no longer just static frontend sites. Thanks to Nitro, the underlying server engine, they run powerful server-side logic, handle API requests, perform database operations, and orchestrate complex SSR flows. This hybrid nature, while incredibly efficient, introduces layers of complexity that demand comprehensive monitoring.

Why New Relic for your Nuxt backend?

  • SSR Performance: Understand the server-side rendering duration, identify slow data fetches, and pinpoint bottlenecks that impact Time To First Byte (TTFB).
  • API Route Latency: Monitor the performance of your /server/api endpoints, ensuring your backend services respond quickly.
  • Database & External Service Calls: Track the performance of your interactions with databases (e.g., Prisma, Drizzle), third-party APIs, and microservices.
  • Error Tracking: Get real-time alerts on server-side errors, detailed stack traces, and context to accelerate debugging.
  • Distributed Tracing: If your Nuxt app interacts with other services, New Relic’s distributed tracing helps you visualize the full request path across your entire architecture.
  • Resource Utilization: Keep an eye on CPU, memory, and I/O usage of your Nuxt server process.

The New Relic Node.js agent focuses on the server-side operations of your Nuxt application. While New Relic also offers browser monitoring for your client-side Nuxt application, this guide will concentrate specifically on the Node.js agent and its integration with your Nuxt server environment.

Setting Up New Relic Node Agent with Nuxt 3

Integrating the New Relic Node.js agent requires careful placement to ensure it initializes before your Nuxt application’s server logic begins. This is critical for comprehensive instrumentation.

Step 1: Install the New Relic Node Agent

First, add the newrelic package to your project:

npm install newrelic
# or yarn add newrelic
# or pnpm add newrelic

Step 2: Configure New Relic (newrelic.js)

Create a newrelic.js file in the root of your Nuxt project. This configuration file tells the agent how to behave, including your application name and license key.

// newrelic.js
/**
 * New Relic agent configuration.
 *
 * See lib/config.defaults.js in the agent distribution for a more complete
 * description of configuration variables and their potential values.
 */
exports.config = {
  /**
   * Array of application names.
   */
  app_name: ['Your Nuxt App Name'],
  /**
   * Your New Relic license key.
   */
  license_key: process.env.NEW_RELIC_LICENSE_KEY,
  /**
   * Log level for the agent.
   */
  logging: {
    level: 'info'
  },
  /**
   * When true, all request headers except for those listed in attributes.exclude
   * will be captured for all traces, unless otherwise specified in a destination-specific
   * section below.
   */
  allow_all_headers: true,
  attributes: {
    /**
     * Prefix of attributes to exclude from all destinations.
     *
     * To disable all attribute collection, use `*`.
     */
    exclude: [
      'request.headers.cookie',
      'request.headers.authorization',
      'request.headers.proxyAuthorization',
      'request.headers.setCookie',
      'request.headers.xForwardedFor'
    ]
  },
  // If you are using async/await, make sure to enable this.
  feature_flag: {
    async_hooks: true
  }
};

You’ll need to set the NEW_RELIC_LICENSE_KEY environment variable. You can do this in your .env file for local development (ensure .env is in .gitignore) or directly in your deployment environment.

# .env
NEW_RELIC_LICENSE_KEY="YOUR_NEW_RELIC_LICENSE_KEY_HERE"

Step 3: Ensure Agent Initialization (Crucial for Nuxt/Nitro)

For the New Relic Node.js agent to effectively instrument your application, it must be the very first module loaded by the Node.js process. Nuxt 3’s server-side code runs within Nitro, which bundles your server logic. The most reliable way to achieve this for a Nuxt production build is by using Node.js’s -r (require) flag.

Modify your package.json start script:

{
  "name": "my-nuxt-app",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "build": "nuxt build",
    "dev": "nuxt dev",
    "generate": "nuxt generate",
    "preview": "nuxt preview",
    "postinstall": "nuxt prepare",
    "start": "node -r newrelic .output/server/index.mjs"
  },
  "dependencies": {
    "newrelic": "^12.x.x"
    // ... other dependencies
  }
}

Now, when you deploy your Nuxt application and run npm run start (or yarn start / pnpm start), Node.js will load the newrelic agent before it loads Nuxt’s bundled server entry point (.output/server/index.mjs). This ensures the agent can properly hook into Node.js modules and instrument your application.

Important Considerations:

  • Development Environment (nuxt dev): The node -r newrelic approach primarily targets your production server runtime. nuxt dev runs a complex development server powered by Vite, and the newrelic agent might not fully instrument it in the same way. For development, you might skip New Relic monitoring or set NEW_RELIC_ENABLED=false in your .env.development if you want to avoid overhead. The focus of the Node.js agent is typically production monitoring.
  • Docker/Containerized Deployments: If you’re using Docker, your CMD or ENTRYPOINT should reflect this:
    # Dockerfile excerpt
    CMD ["node", "-r", "newrelic", ".output/server/index.mjs"]
    

Step 4: Verify Installation

After deploying and starting your application with the modified start script, give it a few minutes to send data. Then, log into your New Relic account and navigate to “APM” -> “Services”. You should see your Nuxt application listed with the name you provided in newrelic.js. Start interacting with your application (e.g., hit some API routes, visit pages that trigger SSR) to generate traffic and data.

Advanced Instrumentation for Nuxt-Specifics

While the New Relic agent auto-instruments many common Node.js modules (HTTP, databases, etc.), you might want to add custom instrumentation for Nuxt-specific logic, especially in your server routes or utilities.

Auto-Instrumented Server Routes

Any /server/api, /server/routes, or /server/middleware defined in your Nuxt 3 project and handled by Nitro will generally be auto-instrumented by New Relic. You’ll see these transactions appear in New Relic APM, showing their response times, throughput, and error rates.

// server/api/products/[id].ts
import { defineEventHandler } from 'h3';
import { getProductById } from '~/server/db/products'; // Assume this makes a DB call

export default defineEventHandler(async (event) => {
  const { id } = event.context.params;

  try {
    const product = await getProductById(id);
    if (!product) {
      setResponseStatus(event, 404);
      return { message: `Product with ID ${id} not found` };
    }
    return product;
  } catch (error) {
    // New Relic will automatically pick up unhandled errors,
    // but explicit noticeError is good for handled exceptions.
    // For this to work, ensure 'newrelic' is available globally or imported
    // (though 'require("newrelic")' on startup makes it globally accessible).
    // Let's explicitly import for clarity, but remember the agent must be *initialized* first.
    // Make sure newrelic is required at the very top of your server process (see Step 3)
    // and then you can import it in your server-side files.
    const nr = require('newrelic');
    nr.noticeError(error);
    setResponseStatus(event, 500);
    return { message: 'Internal Server Error' };
  }
});

Custom Transactions and Metrics

For specific background tasks, long-running operations, or crucial business logic not directly tied to web requests, you can use New Relic’s custom transaction API.

// server/utils/complexCalculator.ts
import newrelic from 'newrelic'; // Import newrelic in server-side files where needed

export async function performComplexCalculation(data: any) {
  // Start a new background transaction for this specific operation
  return newrelic.startBackgroundTransaction('ComplexCalculationService', async () => {
    const transaction = newrelic.getTransaction();
    try {
      console.log('Starting complex calculation...');
      await new Promise(resolve => setTimeout(resolve, Math.random() * 1000)); // Simulate work

      // Record custom metrics
      newrelic.recordMetric('Custom/CalculationService/Invocations', 1);
      newrelic.recordCustomEvent('ComplexCalculationStarted', { inputSize: data.length });

      if (data.includes('error')) {
        throw new Error('Simulated calculation error');
      }

      console.log('Complex calculation finished.');
      return `Result for ${data}`;
    } catch (error) {
      newrelic.noticeError(error); // Record the error in New Relic
      transaction.setTransactionName('ComplexCalculationService/Failed'); // Update transaction name
      throw error;
    } finally {
      // Always end the transaction
      transaction.end();
    }
  });
}

// Example usage in a Nuxt server route:
// server/api/calculate.ts
import { defineEventHandler } from 'h3';
import { performComplexCalculation } from '~/server/utils/complexCalculator';

export default defineEventHandler(async (event) => {
  const body = await readBody(event);
  try {
    const result = await performComplexCalculation(body.data || []);
    return { status: 'success', result };
  } catch (error: any) {
    setResponseStatus(event, 500);
    return { status: 'error', message: error.message };
  }
});

This pattern ensures that even operations not triggered by a direct web request are monitored, providing a complete picture of your application’s health.

Troubleshooting and Common Pitfalls

Even with careful setup, you might encounter issues. Here are some common problems and solutions:

  1. “No Data Appearing in New Relic”:

    • Agent Not Initialized First: This is the most common issue. Double-check that node -r newrelic is the very first part of your start command for production.
    • Incorrect license_key or app_name: Verify these in newrelic.js and your .env file.
    • Network/Firewall Issues: Ensure your server can communicate with New Relic’s data ingest endpoints.
    • Insufficient Traffic: New Relic dashboards might appear empty if there’s no traffic for the agent to instrument. Send some requests to your application.
    • newrelic.js Location: Ensure newrelic.js is in the root directory of your project.
  2. “Errors in New Relic Logs”:

    • Check the logging.level in newrelic.js. Increase it to debug temporarily to get more verbose output from the agent, which might reveal configuration issues.
    • Look at your server’s console output for any newrelic related errors or warnings when the app starts.
  3. “Missing Specific Data Points (e.g., database queries)”:

    • While New Relic auto-instruments many popular modules, some niche libraries might require custom instrumentation.
    • Ensure the auto-instrumented module is actually being required or imported after the New Relic agent has started.
  4. Performance Overhead:

    • Any APM agent adds some overhead. New Relic is generally highly optimized, but in extremely high-traffic or resource-constrained environments, monitor your server’s CPU and memory usage after integration. If concerns arise, you can selectively disable certain features in newrelic.js.

Actionable Takeaways

Integrating New Relic with your Nuxt 3 application is a powerful step towards building resilient and performant web experiences in 2026. By following these steps, you’ll gain:

  • Deep Visibility: Understand every aspect of your server-side Nuxt application’s performance.
  • Proactive Problem Solving: Identify and resolve issues before they impact your users.
  • Performance Optimization: Pinpoint bottlenecks in SSR, API routes, and database interactions.
  • Enhanced Reliability: Monitor errors in real-time and ensure high availability.

The combination of Nuxt’s full-stack power and New Relic’s comprehensive observability ensures your application isn’t just delivering features, but delivering them with excellence and confidence.


Discussion Questions for Readers:

  1. How do you manage your newrelic.js configuration and NEW_RELIC_LICENSE_KEY across different environments (development, staging, production)? Do you use environment variables, CI/CD secrets, or a combination?
  2. Beyond basic setup, what custom New Relic instrumentation patterns have you found most valuable for specific Nuxt 3 features (e.g., composables, server utilities, or specific API integrations)?

Comments

No comments yet. Be the first!

We use cookies to enhance your browsing experience, serve personalized content, and analyze our traffic. By clicking "OK", you consent to our use of cookies and agree to our Terms of Service & Privacy Policy.