Files
firebase/docs/adr/ADR-002-sdk-lifecycle-management.md
Rene Nochebuena 3ef30c2354 feat(firebase): initial stable release v0.9.0
Firebase App component with launcher lifecycle and health check integration.

What's included:
- Config with ProjectID (FIREBASE_PROJECT_ID env var); credentials via ADC
- Provider interface exposing native *firebase.App directly
- Component interface: launcher.Component + health.Checkable + Provider
- New(logger, cfg) constructor for lifecycle registration via lc.Append
- Health check via GetUser("health-probe-non-existent") + auth.IsUserNotFound at LevelCritical
- No-op OnStop (Firebase Admin SDK has no Close method)

Tested-via: todo-api POC integration
Reviewed-against: docs/adr/
2026-03-19 13:35:40 +00:00

2.7 KiB

ADR-002: Firebase SDK Lifecycle Management via launcher.Component

Status: Accepted Date: 2026-03-18

Context

The firebase-admin-go SDK (firebase.google.com/go/v4) manages its own internal gRPC connections, HTTP transports, and credential refresh cycles. The SDK entry point is a *firebase.App instance, obtained via fb.NewApp(ctx, config). Service-specific clients (Auth, Firestore, etc.) are obtained from the App on demand via app.Auth(ctx) and app.Firestore(ctx).

Applications that construct the App outside of a lifecycle manager risk:

  • Attempting to use the App before it is initialised.
  • Not having a clear shutdown point (the SDK has no explicit Close method on App).
  • Difficulty in testing components that depend on Firebase.

Decision

firebaseComponent implements launcher.Component with three lifecycle methods:

  • OnInit: Validates that Config.ProjectID is non-empty, then calls fb.NewApp to create the App and store it in the struct. Returns an error if project ID is missing or if the SDK fails to create the App. No network calls are made at this point — the SDK is lazy about establishing connections.

  • OnStart: Logs that the app is ready. Currently a no-op beyond logging; the SDK does not require an explicit start call.

  • OnStop: Logs shutdown. The firebase-admin-go SDK has no Close method on *fb.App. Connections managed by the SDK (gRPC channels, HTTP transport) are closed by the Go runtime's garbage collector when the App is no longer referenced. This is the accepted behaviour of the SDK.

Consumers access the App via App() *fb.App (the Provider interface) and then obtain service-specific clients themselves:

authClient, err := component.App().Auth(ctx)
firestoreClient, err := component.App().Firestore(ctx)

This keeps the firebase module focused on App lifecycle without prescribing which Firebase services consumers use.

Consequences

Positive:

  • Firebase App creation is integrated into the application startup sequence. Failures (bad credentials, missing project ID) surface at startup, not at the first API call.
  • The module is minimal: OnInit + OnStart + OnStop cover the full SDK lifecycle.
  • Consumers are not limited to Auth; they can use any service the SDK supports.

Negative:

  • There is no explicit SDK shutdown. The OnStop method is effectively a log-and-return. In-flight requests to Firebase at shutdown time are handled by the SDK's own timeouts and the context cancellation of callers, not by this module.
  • App() returns nil before OnInit is called. Consumers must not call App() before the lifecycle has been initialised (this is verified by TestComponent_App_ReturnsNilBeforeInit).