
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
To successfully scale and monitor Next.js in production, you must move beyond default Vercel deployments and treat the application as a distributed Node.js system requiring explicit resource management. High-traffic applications serving global audiences—whether from Kathmandu or AWS us-east-1—demand containerized orchestration with Horizontal Pod Autoscaling (HPA) and deep OpenTelemetry instrumentation rather than simple uptime checks. This guide provides the exact Kubernetes manifests, telemetry configurations, and SLO definitions I use to keep Next.js apps performant and observable under load.
How do you configure Kubernetes autoscaling for Next.js?
Next.js running in "standalone" mode is a stateless Node.js process, making it an ideal candidate for horizontal scaling. However, a common mistake is deploying without proper resource requests or liveness probes, causing the cluster autoscaler to over-provision or pods to crash during traffic spikes. When you configure Kubernetes resource limits and requests correctly, the scheduler can make intelligent placement decisions that prevent noisy-neighbor issues.
Optimizing the Standalone Build
Before configuring autoscaling, ensure your next.config.js outputs a standalone bundle. This reduces the Docker image size from ~1GB to ~150MB, drastically improving pod startup time during scale-out events.
// next.config.js
module.exports = {
output: 'standalone',
experimental: {
serverActions: { allowedOrigins: ['*'] }
}
} Defining HPA Manifests
For CPU-bound SSR workloads, target 70% average utilization. Setting this too high (90%) risks throttling before new pods are ready; setting it too low (40%) wastes budget. Always pair HPA with readiness probes that check /api/health to prevent routing traffic to initializing pods.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: nextjs-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nextjs-app
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleUp:
stabilizationWindowSeconds: 30
scaleDown:
stabilizationWindowSeconds: 300 How do you implement OpenTelemetry in Next.js for observability?
Logs alone cannot explain why a specific user experienced a 4-second delay during checkout. You need distributed tracing to correlate frontend renders with backend database queries. Understanding how metrics, logs, and traces differ helps you avoid instrumenting everything and instead focusing on critical paths. Next.js 14+ includes native OpenTelemetry support, but production setups require manual configuration to export data reliably.
Registering the Instrumentation Hook
Create an instrumentation.ts file in your project root. This runs once when the Node.js runtime starts, registering exporters without adding overhead to individual requests. Use the OTLP exporter for vendor-neutral compatibility.
// instrumentation.ts
import { registerOTel } from '@vercel/otel'
export function register() {
registerOTel({
serviceName: 'nextjs-production',
attributes: {
'deployment.environment': process.env.NODE_ENV,
'service.version': process.env.NEXT_PUBLIC_APP_VERSION
}
})
} Capturing Business-Critical Spans
Automatic instrumentation covers HTTP and database calls, but business logic often lives in plain functions. Wrap critical operations like payment processing or inventory checks in manual spans to capture their duration and status within the trace context.
import { trace } from '@opentelemetry/api'
const tracer = trace.getTracer('checkout-service')
export async function processCheckout(cartId: string) {
return tracer.startActiveSpan('process-checkout', async (span) => {
try {
span.setAttribute('cart.id', cartId)
const result = await validateAndCharge(cartId)
span.setStatus({ code: 1 }) // OK
return result
} catch (error) {
span.recordException(error)
span.setStatus({ code: 2, message: error.message })
throw error
} finally {
span.end()
}
})
} Which metrics matter most when monitoring Next.js performance?
Dashboards filled with generic Node.js heap statistics rarely help during incidents. Focus on the four golden signals of monitoring: latency, traffic, errors, and saturation. For Next.js specifically, distinguish between static generation time and dynamic SSR latency, as they have vastly different operational characteristics and scaling implications.
| Metric Name | Type | Why It Matters for Next.js | Recommended Threshold |
|---|---|---|---|
http.server.request.duration | Histogram | < 800ms p95 for SSR pages | |
nextjs.render.duration | Histogram | Isolates React rendering time from DB/network IO; identifies component bottlenecks< 300ms p95 | |
http.server.response.status_code | Counter | Track 5xx rates separately from 4xx; rising 5xx indicates infra or code failure< 0.1% error rate | |
nodejs.eventloop.delay | Gauge | Detects blocking JS preventing request handling; more reliable than CPU for Node< 100ms p99 | |
nextjs.cache.hit_ratio | Gauge | Low ISR/cache hit rates mean excessive origin load; validates caching strategy> 85% for content pages |
Exposing Custom Metrics Endpoints
While OpenTelemetry handles traces, Prometheus scraping remains the standard for metrics. Configure your Next.js standalone server to expose a /metrics endpoint using prom-client. Ensure this endpoint is excluded from public ingress rules to prevent metric leakage.
// lib/metrics.ts
import client from 'prom-client'
export const httpRequestDuration = new client.Histogram({
name: 'http_server_request_duration_seconds',
help: 'Duration of HTTP requests in seconds',
labelNames: ['method', 'route', 'status_code'],
buckets: [0.01, 0.05, 0.1, 0.3, 0.8, 1.5, 3]
})
// In your API route or middleware
client.register.setDefaultLabels({
service: 'nextjs-app',
region: process.env.AWS_REGION || 'local'
}) How do you define SLOs and alerts for Next.js reliability?
Alerting on every CPU spike creates fatigue. Instead, define meaningful SLIs and SLOs that reflect actual user happiness. A robust SLO for Next.js might be "99.9% of interactive page loads complete within 1.5 seconds over a 30-day window." This allows brief periods of degradation during deploys while catching chronic performance regressions.
Writing Multi-Window Burn Rate Alerts
Single-window alerts fire on noise. Multi-window alerts require both a fast-burning short window and a confirming long window to trigger. This pattern catches genuine outages within minutes while ignoring harmless blips.
# PrometheusRule for Next.js Latency SLO
groups:
- name: nextjs-slo-alerts
rules:
- alert: NextJSLatencyBudgetBurnHigh
expr: |
(
histogram_quantile(0.95, rate(http_server_request_duration_seconds_bucket[1h])) > 1.5
)
and
(
histogram_quantile(0.95, rate(http_server_request_duration_seconds_bucket[6h])) > 1.5
)
for: 5m
labels:
severity: critical
team: frontend-platform
annotations:
summary: "Next.js p95 latency consuming error budget at 14.4x rate"
runbook_url: "/runbooks/nextjs-latency-degradation" Integrating with Incident Response
When an SLO alert fires, context matters more than raw metrics. Configure Alertmanager to inject relevant Grafana dashboard links and recent deployment versions into the notification. Teams managing blue-green and canary deploys on Kubernetes should automatically correlate alerts with rollout stages to identify bad releases instantly.
Scale and Monitor Next.js in Production: Final Checklist
Reliable Next.js operations require treating the framework as a production distributed system, not just a frontend tool. Verify these five items before your next major release:
- Standalone Output: Confirm
output: 'standalone'is set and Dockerfile copies only the necessary artifacts to minimize image size and cold start time. - Resource Boundaries: Every pod has explicit CPU/memory requests matching its actual p99 usage profile; no "best effort" QoS class in production.
- Telemetry Pipeline: OpenTelemetry traces flow end-to-end from browser to database with consistent trace IDs; verify sampling rates don't drop critical errors.
- SLO Definitions: At least one latency and one availability SLO exists with agreed-upon error budgets; alerts use multi-window burn rates.
- Load Testing: Synthetic traffic tests validate autoscaling triggers and cache hit ratios before real users arrive; never assume HPA works without proof.
If your team needs help designing observable Next.js architectures or passing compliance audits with automated evidence collection, reach out to discuss your infrastructure requirements. Building systems that survive peak traffic and satisfy auditors requires the same discipline: measure everything, automate responses, and trust verified data over assumptions.