Temporal Cloud #

Dalam arsitektur sistem terdistribusi modern, mengelola proses bisnis yang kompleks lintas microservices dan layanan serverless menghadirkan tantangan teknis yang sangat berat. Berbeda dengan aplikasi monolitik tradisional di mana transaksi database dapat dikelola dengan mudah menggunakan database transaction block (ACID), sistem terdistribusi tidak memiliki status tunggal (shared state). Proses bisnis seperti pemesanan e-commerce, persetujuan bertingkat, pemrosesan transaksi finansial, atau integrasi dengan pihak ketiga sering kali melibatkan banyak API eksternal, latensi jaringan yang tidak terduga, serta potensi kegagalan parsial (partial failures). Jika salah satu layanan di tengah jalan mengalami kegagalan, sistem dapat berada dalam status tidak konsisten.

Secara tradisional, para developer mencoba memecahkan masalah ini dengan merancang pola desain Saga Pattern manual, mengandalkan antrean pesan (message queues seperti RabbitMQ atau Kafka), menjalankan penjadwal berkala (cron jobs), atau menggunakan database relasional sebagai penyimpan status (state machine). Namun, pendekatan ini cepat sekali menjadi kompleks. Kode program dipenuhi oleh logika penanganan kegagalan (exception handling), mekanisme percobaan ulang dengan jeda (retry with exponential backoff), serta tabel status database yang rumit untuk dipelihara. Overhead operasional dan beban penulisan kode tambahan ini menghambat inovasi fitur bisnis utama.

Temporal Cloud hadir sebagai solusi revolusioner untuk mengatasi kerumitan orkestrasi sistem terdistribusi tersebut. Berbasis pada mesin orkestrasi open-source Temporal, Temporal Cloud bertindak sebagai layanan fully-managed (SaaS) yang memungkinkan kita menulis alur kerja (workflows) sebagai kode program deterministik biasa menggunakan bahasa pemrograman populer (seperti Go, TypeScript, Java, atau Python). Temporal Cloud menjamin ketahanan eksekusi (durable execution), di mana setiap langkah proses bisnis dijamin pasti berjalan hingga selesai, tahan terhadap kegagalan infrastruktur, dan dapat dipantau secara transparan melalui event history yang persisten.


Apa Itu Temporal Cloud dan Mengapa Kita Membutuhkannya? #

Temporal Cloud adalah platform orkestrasi alur kerja (workflow orchestration) terdistribusi yang dijalankan sebagai layanan cloud terkelola penuh. Inti dari keunikan Temporal adalah konsep Workflow as Code. Alih-alih mendefinisikan alur kerja menggunakan file konfigurasi statis seperti JSON, YAML (seperti AWS Step Functions atau Google Cloud Workflows), atau melalui desainer visual drag-and-drop, Temporal memungkinkan kita menulis logika bisnis menggunakan konstruksi kode standar seperti percabangan if-else, perulangan for-loop, penanganan error try-catch, serta fungsi pemrograman lainnya.

Alasan utama organisasi beralih ke Temporal Cloud adalah jaminan terhadap ketahanan eksekusi (durable execution). Ketahanan eksekusi berarti jika server tempat kode kita berjalan mati mendadak (misalnya karena out of memory, kegagalan jaringan, atau restart kluster Kubernetes), status persis dari eksekusi alur kerja kita tidak akan hilang. Ketika server pengganti bangkit kembali, Temporal secara otomatis melanjutkan eksekusi dari baris kode terakhir yang berhasil dieksekusi sebelum kegagalan terjadi, tanpa mengulangi proses dari awal yang sudah sukses dijalankan.

Selain itu, mengoperasikan kluster Temporal secara mandiri (self-hosted) memerlukan pengelolaan database berskala besar (seperti Cassandra, Elasticsearch, atau PostgreSQL) yang sangat kompleks untuk menyimpan riwayat eksekusi. Dengan menggunakan Temporal Cloud, tim developer dibebaskan dari kerumitan administrasi infrastruktur database tersebut. Temporal Cloud menangani scaling, pencadangan data, pembaruan keamanan, serta menjamin ketersediaan tinggi (high availability) dengan kesepakatan tingkat layanan (SLA) kelas industri, sehingga kita dapat fokus sepenuhnya pada penulisan logika bisnis aplikasi.


Pilar Utama Arsitektur Temporal Cloud #

Desain arsitektur Temporal Cloud didasarkan pada pemisahan yang sangat ketat antara komponen Control Plane (yang disediakan oleh Temporal Cloud) dan Execution Plane (yang dijalankan di infrastruktur milik kita sendiri). Pemisahan ini memberikan jaminan keamanan data yang sangat tinggi karena kode program sensitif kita tidak pernah dikirim atau dijalankan di server milik Temporal Cloud.

flowchart TD
    subgraph ClientVPC["Lingkungan Klien (VPC/Kubernetes)"]
        direction TB
        AppClient["Klien Aplikasi (API Gateway)"]
        Worker["Temporal Worker (Menjalankan Kode Workflow & Activity)"]
        DB["Database Aplikasi (PostgreSQL/MySQL)"]
    end

    subgraph TemporalCloud["Layanan Temporal Cloud (SaaS Control Plane)"]
        direction TB
        FrontEnd["Gateway Front-end mTLS"]
        Matching["Matching Service (Rute Antrean Task Queue)"]
        History["History Service (Penyimpan Riwayat Event)"]
        DBPersistence["Layer Persistence (Spanner/Cassandra)"]
    end

    AppClient -->|"1. Start Workflow (mTLS)"| FrontEnd
    FrontEnd --> Matching
    Matching -->|"2. Distribusi Task"| Worker
    Worker -->|"3. Eksekusi & Update Status"| FrontEnd
    FrontEnd --> History
    History --> DBPersistence
    Worker -. "4. Baca/Tulis Data" .-> DB

    style Worker stroke:#0288d1,stroke-width:2px
    style FrontEnd stroke:#0288d1,stroke-width:2px
    style History stroke:#0288d1,stroke-width:2px

1. Gateway Front-end mTLS #

Semua komunikasi antara aplikasi kita dengan Temporal Cloud wajib melewati pintu gerbang Gateway Front-end yang sangat aman. Komunikasi ini menggunakan protokol enkripsi dua arah (mutual TLS atau mTLS). Kita harus mendaftarkan sertifikat Otoritas Sertifikat (CA) kita di konsol Temporal Cloud, dan setiap koneksi dari klien atau worker harus menyertakan sertifikat klien yang valid untuk proses otentikasi dan otorisasi.

2. Matching Service #

Matching Service bertanggung jawab untuk mengelola antrean kerja (Task Queues). Ketika sebuah langkah alur kerja harus dieksekusi, Temporal Cloud menempatkan tugas tersebut ke dalam antrean Task Queue. Komponen worker yang berjalan di server kita akan secara aktif melakukan polling ke Matching Service untuk mengambil tugas yang siap dikerjakan. Ini berarti kita tidak perlu membuka port jaringan masuk (inbound port) pada jaringan privat kita; semua koneksi bersifat keluar (outbound) menuju Temporal Cloud.

3. History Service #

History Service adalah jantung dari keandalan Temporal. Setiap kali ada perubahan status dalam alur kerja (seperti alur kerja dimulai, tugas ditugaskan ke worker, tugas selesai, atau terjadi kegagalan), History Service mencatat kejadian tersebut sebagai urutan kejadian (event history) yang tidak dapat diubah (immutable). Riwayat ini disimpan secara aman di layer persistence terdistribusi milik Temporal Cloud.

4. Execution Plane (Workers) #

Komponen worker adalah aplikasi yang kita tulis, kita bangun sebagai kontainer, dan kita jalankan di infrastruktur kita sendiri (seperti AWS ECS, EKS, Google Cloud Run, atau VM). Worker memuat kode pustaka SDK Temporal bersama dengan definisi fungsi bisnis kita. Worker berkomunikasi dengan Temporal Cloud melalui koneksi mTLS keluar untuk mengambil tugas (tasks), mengeksekusinya secara lokal, dan mengembalikan hasilnya kembali ke Temporal Cloud. Karena kode dijalankan secara lokal di VPC kita, kode tersebut dapat mengakses database privat, cache, atau microservices internal lainnya dengan aman tanpa mengeksposnya ke internet.


Memahami Konsep Fundamental Temporal #

Untuk membangun aplikasi menggunakan Temporal Cloud, kita harus memahami lima konsep dasar berikut yang menyusun ekosistem Temporal:

1. Workflows #

Workflow adalah definisi alur proses bisnis dari awal hingga akhir. Ditulis sebagai fungsi dalam bahasa pemrograman pilihan kita, workflow bertindak sebagai konduktor orkestrasi. Tugas utamanya adalah mengatur urutan eksekusi langkah-langkah kerja, mengelola status alur kerja, mendengarkan sinyal eksternal (signals), serta menangani kegagalan. Aturan paling krusial untuk kode workflow adalah ia harus bersifat deterministik. Artinya, jika kode dijalankan beberapa kali dengan input yang sama, ia harus menghasilkan jalur eksekusi dan hasil yang sama persis tanpa efek samping (side effects).

2. Activities #

Activity adalah unit kerja tunggal dalam alur proses bisnis. Berbeda dengan workflow, kode di dalam activity tidak harus deterministik. Di sinilah kita menaruh semua kode yang berinteraksi dengan dunia luar atau memiliki efek samping, seperti melakukan kueri ke database aplikasi, mengirimkan request HTTP ke API pihak ketiga, membaca berkas dari disk lokal, atau menghasilkan angka acak. Jika sebuah activity gagal karena masalah jaringan, Temporal akan secara otomatis melakukan percobaan ulang (retry) sesuai dengan kebijakan yang kita definisikan.

3. Workers #

Worker adalah proses komputasi yang secara konstan mendengarkan antrean tugas (Task Queue) di Temporal Cloud. Worker bertanggung jawab untuk menerima instruksi eksekusi workflow atau activity, menjalankan fungsi kode yang sesuai secara lokal, dan mengirimkan kembali laporan hasil eksekusi (sukses maupun error) ke Temporal Cloud. Kita dapat menjalankan banyak instans worker secara horizontal untuk membagi beban kerja secara dinamis.

4. Task Queues #

Task Queue adalah antrean pesan ringan yang berada di dalam layanan Temporal Cloud. Task Queue digunakan untuk menghubungkan workflow dan activity dengan worker yang kompeten. Saat mendefinisikan workflow atau mendaftarkan worker, kita menentukan nama Task Queue tertentu (misalnya, order-processing-queue). Hal ini memungkinkan isolasi beban kerja yang fleksibel; kita bisa memiliki worker khusus untuk tugas berat (seperti kompresi video) yang terpisah dari worker untuk tugas umum.

5. Namespaces #

Namespace adalah batas isolasi logis dalam akun Temporal Cloud kita. Semua data alur kerja, antrean tugas, dan riwayat eksekusi terisolasi di dalam namespace tertentu. Biasanya, organisasi membuat beberapa namespace yang berbeda untuk memisahkan lingkungan pengembangan (seperti billing-dev, billing-staging, dan billing-prod), atau memisahkan antar departemen bisnis dalam satu organisasi demi keamanan dan kemudahan manajemen kuota.


Mekanisme Replay Engine: Bagaimana State Diselamatkan Saat Kegagalan #

Rahasia di balik kemampuan Temporal melanjutkan eksekusi yang terputus tanpa kehilangan status terletak pada teknologi Replay Engine yang dikombinasikan dengan pola Event Sourcing.

Ketika sebuah workflow dijalankan, setiap kali workflow memanggil sebuah activity atau melakukan operasi asinkron (seperti menunggu waktu tidur/sleep), Temporal SDK tidak langsung menjalankan kode tersebut secara berulang di memori lokal. Sebaliknya, SDK akan mengirimkan perintah ke Temporal Cloud untuk mencatat kejadian tersebut di Event History. Setelah itu, worker dapat membebaskan memori eksekusi tersebut (suspend).

Jika worker yang sedang memproses workflow tersebut tiba-tiba mati atau mengalami crash di tengah jalan, langkah-langkah pemulihan berikut akan terjadi:

  1. Temporal Cloud mendeteksi bahwa worker tidak lagi aktif mengirimkan detak jantung (heartbeat).
  2. Temporal Cloud menempatkan kembali tugas orkestrasi workflow tersebut ke antrean Task Queue.
  3. Instans worker lain yang aktif mengambil tugas tersebut dari antrean.
  4. Worker baru mengunduh seluruh Event History dari alur kerja tersebut dari database Temporal Cloud.
  5. Proses Replay: Worker baru menjalankan kembali fungsi kode workflow dari awal. Namun, setiap kali kode mencapai pemanggilan activity yang sebelumnya sudah sukses dieksekusi (berdasarkan catatan di Event History), SDK akan memotong komputasi lokal dan langsung mengembalikan hasil yang tercatat di riwayat kejadian tersebut tanpa mengeksekusi ulang fungsi activity fisik secara nyata.
  6. Begitu proses replay mencapai titik persis di mana worker sebelumnya mati, worker baru melanjutkan eksekusi secara normal seolah-olah tidak pernah terjadi gangguan.

Karena mekanisme replay ini mengeksekusi kembali kode workflow dari awal, maka aturan determinisme menjadi harga mati.

// ANTI-PATTERN: Menggunakan fungsi non-deterministik langsung di dalam Workflow
func BadWorkflow(ctx workflow.Context) error {
    // ✗ JANGAN: Nilai waktu akan berbeda saat replay dijalankan
    currentTime := time.Now() 
    if currentTime.Hour() > 12 {
        err := workflow.ExecuteActivity(ctx, SendAfternoonEmail).Get(ctx, nil)
        return err
    }
    return nil
}

// BENAR: Menggunakan pustaka internal Temporal untuk menjaga determinisme
func GoodWorkflow(ctx workflow.Context) error {
    // ✓ BENAR: Menggunakan waktu dari context Temporal yang konsisten saat replay
    currentTime := workflow.Now(ctx) 
    if currentTime.Hour() > 12 {
        err := workflow.ExecuteActivity(ctx, SendAfternoonEmail).Get(ctx, nil)
        return err
    }
    return nil
}

Jika di dalam kode workflow terdapat fungsi non-deterministik (seperti kueri database langsung, memanggil API HTTP eksternal, atau menggunakan random number generator bawaan bahasa pemrograman), maka saat replay dijalankan, alur kode bisa mengambil jalur percabangan yang berbeda dari eksekusi asli. Hal ini akan memicu Non-Deterministic Error yang menyebabkan eksekusi alur kerja diblokir demi menjaga integritas data.


Kebijakan Retry (Retry Policy) dan Penanganan Timeout secara Detail #

Salah satu fitur terkuat dari Temporal Cloud adalah manajemen kegagalan terdistribusi yang sangat granular melalui konfigurasi waktu tunggu (timeouts) dan kebijakan percobaan ulang (retry policies).

4 Jenis Timeout pada Activity #

Mengonfigurasi timeout secara tepat sangat penting untuk mencegah penumpukan tugas dalam antrean saat terjadi kegagalan sistem. Temporal membagi timeout menjadi empat dimensi:

  1. Start-To-Close Timeout: Batas waktu maksimal bagi satu upaya eksekusi activity sejak worker mengambil tugas tersebut hingga worker mengembalikan hasil. Ini adalah timeout yang paling sering digunakan untuk mendeteksi apakah proses worker mengalami crash saat menjalankan tugas.
  2. Schedule-To-Start Timeout: Batas waktu maksimal bagi sebuah tugas berada di antrean Task Queue sebelum diambil oleh worker. Jika timeout ini terlampaui, biasanya menandakan bahwa tidak ada worker yang aktif atau kapasitas worker kita tidak mencukupi untuk memproses beban kueri.
  3. Schedule-To-Close Timeout: Batas waktu maksimal untuk seluruh siklus hidup activity sejak pertama kali dijadwalkan hingga berhasil diselesaikan, termasuk semua upaya percobaan ulang (retry attempts).
  4. Heartbeat Timeout: Batas waktu maksimal antara detak jantung (heartbeat) yang dikirimkan oleh activity yang berjalan lama (seperti proses migrasi data atau kompresi video besar). Jika activity tidak mengirimkan detak jantung dalam batas waktu ini, Temporal menganggap worker telah hang atau terputus dan langsung memicu kegagalan untuk dicoba kembali di worker lain.

Konfigurasi Retry Policy #

Secara default, jika sebuah activity mengalami error, Temporal Cloud akan mencoba menjalankannya kembali secara otomatis. Kita dapat melakukan kustomisasi parameter kebijakan percobaan ulang dengan sangat detail:

  • Initial Interval: Jeda waktu tunggu pertama sebelum melakukan percobaan ulang pertama (misal: 1 detik).
  • Backoff Coefficient: Faktor pengali untuk meningkatkan jeda waktu tunggu secara eksponensial pada setiap upaya kegagalan berikutnya (misal: 2.0, artinya jeda berikutnya menjadi 2s, 4s, 8s, dst).
  • Maximum Interval: Batas atas maksimal jeda waktu tunggu agar jeda eksponensial tidak terus membesar tanpa batas (misal: 100 detik).
  • Maximum Attempts: Batas maksimal jumlah upaya percobaan ulang yang diizinkan sebelum tugas dinyatakan gagal total (misal: 5 kali). Jika diset ke 0, Temporal akan mencoba kembali tanpa batas hingga berhasil.
  • Non-Retryable Error Types: Daftar nama error spesifik yang jika terjadi, Temporal tidak boleh mencoba lagi karena error tersebut bersifat permanen (seperti InvalidInputException atau UnauthorizedException).

Penerapan Kode: Implementasi Go SDK #

Berikut adalah contoh implementasi lengkap orkestrasi pemrosesan pesanan menggunakan Go SDK yang dirancang agar tangguh, aman, dan siap untuk digunakan di lingkungan produksi yang terhubung ke Temporal Cloud.

1. Definisi Tipe Data dan Activity #

Pertama, kita definisikan struktur data transfer dan fungsi-fungsi activity nyata yang melakukan interaksi database serta pemanggilan API eksternal.

package app

import (
	"context"
	"fmt"
	"go.uber.org/zap"
)

// OrderRequest mewakili input dari klien untuk memulai workflow
type OrderRequest struct {
	OrderID     string  `json:"order_id"`
	UserID      string  `json:"user_id"`
	Amount      float64 `json:"amount"`
	ItemName    string  `json:"item_name"`
}

// PaymentResponse mewakili hasil transaksi pembayaran
type PaymentResponse struct {
	TransactionID string `json:"transaction_id"`
	Success       bool   `json:"success"`
}

// OrderActivities mendefinisikan activity yang tersedia
type OrderActivities struct {
	Logger *zap.Logger
}

// ProcessPayment mensimulasikan pemanggilan API payment gateway pihak ketiga
func (a *OrderActivities) ProcessPayment(ctx context.Context, req OrderRequest) (PaymentResponse, error) {
	a.Logger.Info("Memproses pembayaran melalui Payment Gateway", zap.String("OrderID", req.OrderID))
	
	// ANTI-PATTERN: Mengabaikan idempotensi dalam transaksi finansial
	// BENAR: Mengirimkan OrderID sebagai idempotency-key ke API Payment Gateway
	if req.Amount <= 0 {
		// Mengembalikan error non-retryable karena input tidak valid
		return PaymentResponse{}, fmt.Errorf("nominal pembayaran tidak valid: %f", req.Amount)
	}

	// Simulasi pemanggilan API sukses
	return PaymentResponse{
		TransactionID: fmt.Sprintf("TX-%s-12345", req.OrderID),
		Success:       true,
	}, nil
}

// UpdateInventory mengurangi stok barang di database lokal
func (a *OrderActivities) UpdateInventory(ctx context.Context, req OrderRequest) error {
	a.Logger.Info("Mengurangi stok barang di database", zap.String("ItemName", req.ItemName))
	
	// Dalam aplikasi nyata, lakukan query UPDATE ke database di sini
	return nil
}

// SendNotification mengirimkan email konfirmasi ke pengguna
func (a *OrderActivities) SendNotification(ctx context.Context, req OrderRequest, txID string) error {
	a.Logger.Info("Mengirimkan email notifikasi sukses", zap.String("UserID", req.UserID))
	return nil
}

2. Definisi Workflow Deterministik #

Selanjutnya, kita tulis logika orkestrasi di dalam fungsi workflow. Kode ini wajib mematuhi aturan determinisme dan hanya berinteraksi melalui fungsi konteks milik Temporal SDK.

package app

import (
	"time"

	"go.temporal.io/sdk/temporal"
	"go.temporal.io/sdk/workflow"
)

// OrderProcessingWorkflow mengatur urutan pemrosesan pesanan secara durabel
func OrderProcessingWorkflow(ctx workflow.Context, req OrderRequest) error {
	// Konfigurasi Retry Policy untuk Activity
	retryPolicy := &temporal.RetryPolicy{
		InitialInterval:    time.Second * 1,
		BackoffCoefficient: 2.0,
		MaximumInterval:    time.Second * 60,
		MaximumAttempts:    5, // Coba maksimal 5 kali sebelum menyerah
	}

	// Tentukan opsi eksekusi untuk Activity
	activityOptions := workflow.ActivityOptions{
		StartToCloseTimeout: time.Second * 30, // Deteksi crash worker dalam 30 detik
		RetryPolicy:         retryPolicy,
	}
	ctx = workflow.WithActivityOptions(ctx, activityOptions)

	logger := workflow.GetLogger(ctx)
	logger.Info("Memulai orkestrasi Workflow Pemrosesan Pesanan", "OrderID", req.OrderID)

	var activities *OrderActivities

	// 1. Jalankan proses pembayaran
	var paymentResult PaymentResponse
	err := workflow.ExecuteActivity(ctx, activities.ProcessPayment, req).Get(ctx, &paymentResult)
	if err != nil {
		logger.Error("Gagal memproses pembayaran. Workflow dibatalkan.", "Error", err)
		return err
	}

	// 2. Jalankan pembaruan stok inventori
	err = workflow.ExecuteActivity(ctx, activities.UpdateInventory, req).Get(ctx, nil)
	if err != nil {
		logger.Error("Gagal memperbarui inventori. Butuh penanganan manual.", "Error", err)
		return err
	}

	// 3. Kirimkan email notifikasi sukses ke pelanggan
	err = workflow.ExecuteActivity(ctx, activities.SendNotification, req, paymentResult.TransactionID).Get(ctx, nil)
	if err != nil {
		// Kita hanya mencatat log error notifikasi, tidak membatalkan seluruh transaksi
		logger.Warn("Gagal mengirimkan notifikasi email, tetapi transaksi tetap sukses.", "Error", err)
	}

	logger.Info("Workflow Pemrosesan Pesanan Selesai dengan Sukses", "OrderID", req.OrderID)
	return nil
}

3. Kode Worker Produksi #

Terakhir, kita buat kode program worker utama yang mendaftarkan definisi workflow dan activity, lalu menghubungkannya ke layanan Temporal Cloud menggunakan mTLS yang aman.

package main

import (
	"crypto/tls"
	"log"
	"os"

	"app" // sesuaikan dengan path modul Anda
	"go.uber.org/zap"
	"go.temporal.io/sdk/client"
	"go.temporal.io/sdk/worker"
)

func main() {
	// Inisialisasi Logger terstruktur
	zapLogger, _ := zap.NewProduction()
	defer zapLogger.Sync()

	// Ambil konfigurasi kredensial mTLS dari Environment Variables
	certPath := os.Getenv("TEMPORAL_CERT_PATH")
	keyPath := os.Getenv("TEMPORAL_KEY_PATH")
	hostPort := os.Getenv("TEMPORAL_HOST_PORT") // Contoh: namespace-id.tmprl.cloud:7233
	namespace := os.Getenv("TEMPORAL_NAMESPACE")

	if certPath == "" || keyPath == "" || hostPort == "" || namespace == "" {
		log.Fatal("Kredensial mTLS Temporal Cloud belum dikonfigurasi di env")
	}

	// Muat sertifikat klien dan kunci privat untuk otentikasi mTLS
	cert, err := tls.LoadX509KeyPair(certPath, keyPath)
	if err != nil {
		log.Fatalf("Gagal memuat sertifikat mTLS: %v", err)
	}

	// Buat konfigurasi TLS
	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{cert},
	}

	// Buat klien Temporal terkoneksi ke Temporal Cloud
	c, err := client.Dial(client.Options{
		HostPort:  hostPort,
		Namespace: namespace,
		ConnectionOptions: client.ConnectionOptions{
			TLS: tlsConfig,
		},
	})
	if err != nil {
		log.Fatalf("Gagal membuat koneksi ke Temporal Cloud: %v", err)
	}
	defer c.Close()

	// Buat instans worker untuk mendengarkan antrean tugas
	w := worker.New(c, "order-processing-queue", worker.Options{})

	// Daftarkan workflow dan activity ke worker lokal
	w.RegisterWorkflow(app.OrderProcessingWorkflow)
	
	activities := &app.OrderActivities{Logger: zapLogger}
	w.RegisterActivity(activities)

	// Mulai jalankan worker (proses blocking menunggu tugas)
	log.Println("Worker Temporal aktif mendengarkan task queue: order-processing-queue...")
	err = w.Run(worker.InterruptCh())
	if err != nil {
		log.Fatalf("Worker berhenti karena mengalami error: %v", err)
	}
}

Observability, Monitoring, dan Security di Temporal Cloud #

Menjalankan alur kerja penting di lingkungan produksi menuntut pengawasan keamanan dan pemantauan sistem secara ketat.

1. Keamanan Data (Data Encryption on the Wire & Rest) #

  • mTLS untuk Semua Koneksi: Akses menuju API Temporal Cloud dibatasi secara penuh oleh mTLS. Tidak ada lalu lintas data tanpa enkripsi yang diperbolehkan masuk.
  • Payload Codec (Enkripsi Sisi Klien): Meskipun Temporal Cloud menyimpan data input dan output eksekusi di database internal mereka untuk kebutuhan debugging di Web UI, kita dapat mengenkripsi data sensitif tersebut sebelum dikirimkan ke cloud. Menggunakan fitur Data Converter dan Payload Codec bawaan SDK, data dienkripsi di sisi worker menggunakan kunci enkripsi milik kita sendiri (KMS). Dengan demikian, data yang tersimpan di server Temporal Cloud hanyalah berupa sandi terenkripsi yang tidak dapat dibaca oleh pihak luar maupun oleh tim operasional Temporal Cloud.

2. Monitoring Menggunakan Prometheus dan Grafana #

Temporal Cloud mengekspos metrik performa di tingkat server yang dapat kita tarik (scrape) menggunakan Prometheus untuk disajikan ke dalam dashboard Grafana. Metrik utama yang wajib dipantau meliputi:

  • temporal_workflow_started: Jumlah total alur kerja yang dimulai (membantu melacak beban transaksi bisnis).
  • temporal_workflow_failed: Jumlah kegagalan alur kerja yang membutuhkan investigasi segera.
  • schedule_to_start_latency: Latensi antara tugas dijadwalkan hingga diambil oleh worker. Jika metrik ini meningkat tajam, itu adalah sinyal kritis bahwa kita kekurangan kapasitas worker dan harus melakukan skala horizontal (scale-out) instans worker kita.
  • temporal_activity_execution_failed: Frekuensi kegagalan activity per tipe, berguna untuk mendeteksi gangguan API pihak ketiga atau masalah koneksi database eksternal.

Kapan Menggunakan Temporal vs Alternatif (Message Queue / Step Functions) #

Memilih teknologi orkestrasi yang tepat sangat menentukan kebersihan arsitektur kode dan efisiensi biaya infrastruktur.

TETAP GUNAKAN TEMPORAL jika:
  ✓ Proses bisnis memiliki status kompleks yang harus bertahan lama (hari/bulan).
  ✓ Membutuhkan integrasi dengan banyak API eksternal yang rawan kegagalan intermiten.
  ✓ Ingin mendefinisikan alur kerja menggunakan kode program asli (Go/TS/Python) agar mudah di-test.
  ✓ Memerlukan visibilitas audit penuh langkah-demi-langkah (event history) di tingkat enterprise.

PERTIMBANGKAN ALTERNATIF jika:
  ✗ Tugas sangat sederhana, singkat, stateless, dan bertipe fire-and-forget (cukup gunakan Pub/Sub).
  ✗ Seluruh infrastruktur berada di AWS dan lebih memilih visual designer tanpa kode (gunakan AWS Step Functions).
  ✗ Latensi eksekusi harus di bawah 10 milidetik (Temporal memiliki overhead penulisan log history).

Tabel Perbandingan Solusi Orkestrasi #

Dimensi Evaluasi Temporal Cloud Message Queue (Kafka/RabbitMQ) AWS Step Functions (YAML)
Definisi Alur Kerja Kode Program (Go, TS, Python) Logika Tersebar di Konsumen File Manifest YAML / JSON
Penyimpanan Status Otomatis di Cloud (Persisten) Harus Dikelola Sendiri di DB Otomatis di AWS Control Plane
Kemudahan Pengujian Sangat Tinggi (Unit Test Biasa) Sangat Rendah (Butuh Mock Broker) Rendah (Butuh Emulator Lokal)
Batas Waktu Maksimal Tanpa Batas (Bisa Berbulan-bulan) Tergantung TTL Pesan Antrean Maksimal 1 Tahun per Eksekusi
Skalabilitas Skala Global SaaS Terkelola Sangat Tinggi (Butuh Tuning Cluster) Terbatas Kuota AWS API Rate

Ringkasan #

  • Temporal Cloud adalah platform workflow orchestration terkelola penuh (SaaS) berbasis event sourcing untuk menjamin ketahanan eksekusi sistem.
  • Konsep Workflow as Code membebaskan developer menulis logika orkestrasi kompleks menggunakan kode pemrograman terstruktur, bukan manifest YAML statis.
  • Pemisahan Plane yang Ketat menjamin keamanan data karena komponen worker berjalan lokal di VPC kita sendiri, bukan di server Temporal Cloud.
  • Teknologi Replay Engine memulihkan status eksekusi workflow pasca kegagalan dengan mengalirkan kembali kejadian bersejarah secara deterministik.
  • Empat tipe timeout pada Activity (Start-to-Close, Schedule-to-Start, Schedule-to-Close, Heartbeat) mencegah penyumbatan antrean tugas secara cerdas.
  • Otentikasi mTLS dua arah wajib digunakan untuk seluruh komunikasi agen worker menuju platform cloud guna menjamin keamanan saluran data.

← Sebelumnya: Knative   Berikutnya: Supabase →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact