Mengenal Endpoint API v1 Health: Standar, Desain, dan Kode Praktis

Endpoint /api/v1/health adalah rute HTTP standar pada arsitektur REST API dan microservices yang bertugas melaporkan status operasional aplikasi secara berkala ke sistem eksternal, seperti Load Balancer (AWS ALB, NGINX), orchestrator (Kubernetes, Docker Swarm), atau monitoring tool (Datadog, Prometheus, UptimeRobot). Jika aplikasi berjalan normal, endpoint ini wajib mengembalikan status HTTP 200 OK dengan payload ringkas; jika terjadi kegagalan sistem internal, endpoint wajib mengembalikan status HTTP 503 Service Unavailable.

Dalam ekosistem production modern, health check dibagi menjadi dua level: Shallow Health Check (hanya memverifikasi bahwa web server menerima koneksi HTTP) dan Deep Health Check (memverifikasi konektivitas ke database, Redis cache, queue broker, serta storage pihak ketiga). Menyajikan data kesehatan yang tepat mencegah traffic dikirim ke server yang lumpuh sekaligus mencegah reboot loop (cascading failure).

Standar Respons JSON dan Kode HTTP Health Check

Berdasarkan draf standar IETF (RFC Health Check Response Format for HTTP APIs), sebuah response payload health check yang ideal harus mengembalikan struktur terstandarisasi yang mudah di-parse oleh parser otomatis maupun manusia.

HTTP/1.1 200 OK
Content-Type: application/health+json
Cache-Control: no-cache, no-store, must-revalidate

{
  "status": "pass",
  "version": "1.4.2",
  "releaseId": "2026.03.1",
  "uptime": 86420,
  "checks": {
    "database:postgres": [
      {
        "status": "pass",
        "componentType": "datastore",
        "observedValue": "12ms"
      }
    ],
    "cache:redis": [
      {
        "status": "pass",
        "componentType": "cache",
        "observedValue": "2ms"
      }
    ]
  }
}

Matriks Perbandingan: Jenis Health Check di Lingkungan Produksi

Pemilihan tipe pemeriksaan menentukan kestabilan infrastruktur sistem Anda. Tabel berikut merinci perbedaan fungsional tiap jenis probe:

Tipe ProbeFungsi UtamaTarget PemeriksaanHTTP Status NormalTindakan Jika Gagal
Liveness ProbeMemastikan proses/aplikasi tidak mengalami deadlock atau hang.Internal event loop, thread pool, memori dasar.200 OKOrchestrator me-restart container/pod secara paksa.
Readiness ProbeMemastikan aplikasi siap melayani lalu lintas pengguna.Koneksi DB, Redis, migrasi data selesai, warm-up cache.200 OKLoad balancer mencopot pod dari routing traffic sementara (tanpa restart).
Startup ProbeMenunggu aplikasi legacy/berat menyelesaikan inisialisasi awal.Booting JVM/framework, inisialisasi modul besar.200 OKMemberi toleransi waktu sebelum Liveness aktif; mematikan pod jika timeout tercapai.
Deep Health (Admin)Diagnostik mendalam untuk engineer & SRE.Konektivitas disk space, kuota API eksternal, latensi query.200 OK / 207 Multi-Status / 503Pemicu alert pager on-call engineer, tanpa restart otomatis.

Implementasi Kode Endpoint /api/v1/health

Berikut adalah contoh implementasi endpoint /api/v1/health siap pakai untuk beberapa backend framework populer.

1. Node.js (Express.js)

const express = require('express');
const router = express.Router();
const db = require('../config/database'); // Pool PostgreSQL / MySQL

router.get('/health', async (req, res) => {
  const startTime = Date.now();
  const healthStatus = {
    status: 'pass',
    uptime: process.uptime(),
    timestamp: new Date().toISOString(),
    checks: {}
  };

  try {
    // Uji koneksi DB dengan query ringan (ping)
    await db.query('SELECT 1');
    healthStatus.checks.database = { status: 'pass', latency: `${Date.now() - startTime}ms` };
    
    return res.status(200).json(healthStatus);
  } catch (error) {
    healthStatus.status = 'fail';
    healthStatus.checks.database = { status: 'fail', error: error.message };
    
    return res.status(503).json(healthStatus);
  }
});

module.exports = router;

2. Go (Gin Framework)

package main

import (
	"context"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/jackc/pgx/v5/pgxpool"
)

func RegisterHealthCheck(r *gin.Engine, db *pgxpool.Pool) {
	r.GET("/api/v1/health", func(c *gin.Context) {
		ctx, cancel := context.WithTimeout(c.Request.Context(), 2*time.Second)
		defer cancel()

		response := gin.H{
			"status":    "pass",
			"timestamp": time.Now().UTC().Format(time.RFC3339),
		}

		if err := db.Ping(ctx); err != nil {
			response["status"] = "fail"
			response["database"] = "unreachable"
			c.JSON(http.StatusServiceUnavailable, response)
			return
		}

		response["database"] = "connected"
		c.JSON(http.StatusOK, response)
	})
}

3. Python (FastAPI)

from fastapi import APIRouter, Response, status
import asyncpg
import time

router = APIRouter(prefix="/api/v1", tags=["Health"])

@router.get("/health")
async def health_check(response: Response, pool: asyncpg.Pool):
    start_time = time.time()
    try:
        async with pool.acquire() as conn:
            await conn.execute("SELECT 1")
        
        return {
            "status": "pass",
            "database": "connected",
            "latency_ms": round((time.time() - start_time) * 1000, 2)
        }
    except Exception as err:
        response.status_code = status.HTTP_503_SERVICE_UNAVAILABLE
        return {
            "status": "fail",
            "database": "disconnected",
            "error": str(err)
        }

Konfigurasi Probe pada Kubernetes Deployment

Di kluster Kubernetes, Anda harus membedakan rute liveness dan readiness agar tidak terjadi pemadaman beruntun saat database mengalami lonjakan beban sesaat.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: core-api-service
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: api
        image: registry.example.com/api:v1.4.2
        ports:
        - containerPort: 8080
        livenessProbe:
          httpGet:
            path: /api/v1/health/live
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 15
          timeoutSeconds: 3
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /api/v1/health/ready
            port: 8080
          initialDelaySeconds: 15
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 2

Aturan Desain & Praktik Pengamanan Health Check

  1. Hindari Beban Query Berat: Jangan pernah mengeksekusi query kompleks seperti SELECT COUNT(*) atau pemindaian tabel besar. Gunakan SELECT 1 atau perintah PING native client.
  2. Terapkan Timeout Ketat: Berikan batasan waktu maksimum (maksimal 2–3 detik) pada koneksi dependen dalam health check. Jika dependensi macet, health check harus segera mengembalikan status timeout tanpa membuat thread aplikasi terbengkalai.
  3. Pisahkan Akses Publik dan Private: Jangan ekspos data sensitif arsitektur internal (seperti string koneksi, host IP, versi database mendalam) pada endpoint publik. Lindungi deep metrics di balik reverse proxy atau require header token khusus jika endpoint diakses oleh publik.
  4. Cegah Efek Domino (Cascading Restart): Liveness probe tidak boleh memeriksa database. Jika database global mengalami downtime, seluruh pod API Anda akan di-restart serentak oleh Kubernetes jika liveness bergantung pada database, yang justru memperburuk utilisasi server CPU/RAM.