Membangun plugin backend di Backstage dengan New Backend System: createBackendPlugin dan createBackendModule, service APIs, plugin options, serta testing dengan backend-test-utils. Ditutup dengan cara mengintegrasikan plugin ke backend proxy, auth, catalog, dan scaffolder.

Di episode 17 kalian membangun plugin dari sisi frontend dengan New Frontend System: membuat ekstensi, menghubungkan halaman dan komponen ke halaman entitas. Episode 18 ini melengkapi ceritanya dari sisi server. Backstage bukan hanya kumpulan UI — di balik setiap plugin frontend biasanya ada plugin backend yang menyediakan data, endpoint HTTP, dan jembatan ke sistem internal. Di sini kalian mempelajari New Backend System: mendefinisikan plugin dan module, memakai service APIs, menyetel opsi plugin, menguji semuanya, lalu merangkainya ke backend yang sudah ada seperti proxy, auth, catalog, dan scaffolder.
New Backend System adalah fondasi arsitektur plugin backend Backstage. Sebelumnya setiap plugin disambung langsung di dalam kode backend dan mendaftarkan dirinya dengan memanggil API dari app-backend. Sekarang plugin dan module bersifat deklaratif: kalian menulis definisi plugin, lalu menyusunnya seperti lego di satu titik masuk bernama backend.
Ada tiga unit bangunan utama yang perlu dipahami:
| Unit | Tujuan | Kapan Dipakai |
|---|---|---|
createBackendPlugin | Membuat plugin backend yang berdiri sendiri | Setiap kali ada plugin backend baru |
createBackendModule | Menyuntikkan fitur ke plugin lain | Integrasi lintas plugin, custom logic tambahan |
| Service APIs | Layanan bersama yang dipakai antar plugin | Mengakses config, database, logger, auth, catalog |
Ketiganya bekerja sama: plugin menyediakan fitur, module memperluas, dan service menyalurkan fungsi yang sama ke semua plugin.
createBackendPlugin adalah fungsi untuk mendefinisikan plugin backend. Sebuah plugin backend minimal punya pluginId unik dan fungsi register yang menghubungkan plugin ke backend:
import { createBackendPlugin, coreServices } from '@backstage/backend-plugin-api';
export const healthPlugin = createBackendPlugin({
pluginId: 'health',
register(env) {
env.registerInit({
deps: { logger: coreServices.logger, httpRouter: coreServices.httpRouter },
async init({ logger, httpRouter }) {
httpRouter.use('/healthz', (_req, res) => {
logger.info('health check dipanggil');
res.json({ status: 'ok' });
});
},
});
},
});Plugin ini menyediakan endpoint HTTP baru lewat httpRouter. Setelah dipasang di titik masuk backend dengan backend.add, router dan logger-nya langsung tersedia tanpa setup tambahan.
Modul adalah unit yang memperluas plugin lain. Pola yang umum adalah mendaftarkan diri ke sebuah extension point milik plugin target:
import { createBackendModule } from '@backstage/backend-plugin-api';
export const customScaffolderModule = createBackendModule({
pluginId: 'scaffolder',
moduleId: 'custom-actions',
register(env) {
env.registerInit({
deps: {
scaffolder: scaffolderActionsExtensionPoint,
logger: coreServices.logger,
},
async init({ scaffolder, logger }) {
scaffolder.addActions(new MyCustomAction({ logger }));
},
});
},
});Modul terikat pada pluginId dari plugin yang diperluas. Contoh di atas menambah action baru ke scaffolder tanpa menyentuh kode plugin scaffolder itu sendiri. Ini bentuk ekstensibilitas yang membuat Backstage mudah disesuaikan tanpa fork repositori.
Service API adalah kontrak layanan yang disediakan Backstage: config, logger, database, cache, auth, httpAuth, httpRouter, catalog, permissions, dan masih banyak lagi. Plugin meminta layanan lewat deklarasi deps, bukan dengan mengimpor implementasi secara langsung — Backstage yang memutuskan bagaimana layanan itu diwujudkan, termasuk bagaimana ia berperilaku saat pengujian.
Untuk layanan milik kalian sendiri, daftarkan lewat createServiceFactory:
import { createServiceRef, createServiceFactory } from '@backstage/backend-plugin-api';
export const reportingServiceRef = createServiceRef<ReportingService>({ id: 'acme.reporting' });
export const reportingServiceFactory = createServiceFactory({
service: reportingServiceRef,
deps: { logger: coreServices.logger, config: coreServices.rootConfig },
async factory({ logger, config }) {
return new ReportingService({ logger, endpoint: config.getString('reporting.url') });
},
});Custom service yang didaftarkan dengan createServiceFactory bisa diminta plugin lain lewat deps — cara yang bersih untuk berbagi koneksi database, klien HTTP, atau helper internal lintas plugin.
Plugin backend sering membutuhkan pengaturan khusus. New Backend System mendukung plugin options yang didefinisikan di fungsi pembuat plugin:
import { createBackendPlugin } from '@backstage/backend-plugin-api';
import { z } from 'zod';
export const reportingPlugin = createBackendPlugin({
pluginId: 'reporting',
options: {
endpoint: z.string().url(),
retries: z.number().default(3),
},
async register(env, options) {
env.registerInit({
deps: { httpRouter: coreServices.httpRouter },
async init({ httpRouter }) {
httpRouter.use('/reports', new ReportsRouter(options));
},
});
},
});Saat dipasang, nilai opsi diteruskan bersama pemanggilan backend.add:
backend.add(reportingPlugin, { endpoint: 'https://reports.internal', retries: 5 });Dengan opsi, satu plugin bisa dipakai ulang dengan konfigurasi berbeda tanpa menggandakan kode.
@backstage/backend-test-utils menyediakan mock services dan harness untuk menjalankan backend uji tanpa server sungguhan:
import { startTestBackendFromFeatures, mockServices } from '@backstage/backend-test-utils';
const backend = await startTestBackendFromFeatures({
features: [
reportingPlugin,
mockServices.config.factory({
data: { reporting: { url: 'https://test.internal' } },
}),
],
});Harness semacam ini juga menyediakan setupRequestHandlerContext untuk menguji route HTTP tertentu. Dengan test harness, plugin teruji dalam isolasi yang realistis: service-service yang dibutuhkan di-mock, dan hanya plugin yang sedang diuji yang aktif.
Kelebihan utama arsitektur plugin adalah kemudahan integrasi. Kebutuhan yang sering muncul:
httpAuth atau auth; Backstage yang mengelola token, sesi, dan provider sign-in.catalog, atau menambah processor sendiri untuk data kustom.Semua integrasi ini diekspresikan lewat service APIs dan module, jadi kalian tidak perlu meretas ke dalam kode plugin lain.
Tip
Pola paling umum untuk integrasi backend: module + extension point. Jika plugin target mengekspos extension point, daftar lewat module, bukan mengubah konfigurasi global. Ini menjaga plugin tetap deklaratif dan memudahkan upgrade versi Backstage di kemudian hari.
Pada episode 18 ini, kalian memahami New Backend System: membangun plugin dengan createBackendPlugin, memperluas plugin lain dengan createBackendModule, memakai service APIs seperti config, logger, database, dan catalog, menyetel plugin options, menguji plugin dengan @backstage/backend-test-utils, serta mengintegrasikannya dengan backend proxy, auth, catalog, dan scaffolder lewat custom service registration.
Inti yang harus dibawa pulang:
createBackendPlugin, lalu pasang lewat backend.add.deps, Backstage yang menyediakan layanannya.Di episode 19, kalian naik tingkat dari satu instance ke banyak instance: scaling & performance. Kita akan menata Backstage agar melayani ribuan engineer — mulai dari horizontal scaling, load balancing, database bersama PostgreSQL, task scheduler untuk pipeline, hingga optimasi bundling size, memory management, dan cache strategy.