Overview
The Go backend is a read-only consumer of identity and organization data managed by the Bun monolith via Better Auth. This document explains the technical implementation of this integration, ensuring type-safe and performant access to the shared PostgreSQL schema.1. Shared PostgreSQL Strategy
Go microservices skip the synchronization layer (NATS sync) and query the Better Auth tables directly. To maintain compatibility, Go models must exactly match the schema generated by the Better Auth plugins.Standardized Table Names (Plural)
users: Managed by Better Auth core + Admin plugin.organizations: Managed by Organization plugin.members: Managed by Organization plugin (User-Org join table).accounts: Managed by Better Auth core (OAuth/Social).
2. Admin Plugin Integration (Platform Roles)
The Admin Plugin on the Bun backend adds arole field to the users table. The Go backend resolves this role during JWT validation or through high-performance database lookups.
Role Extraction
ThePermissionService resolves platform permissions by querying the role column in the users table:
user: Basic access.admin/superadmin: Elevated system-wide access.
Read-Only Repository Pattern
TheUserRepository in Go is restricted to SELECT operations. Mutations (e.g., changing a platform role) must be performed via the Bun backend’s Better Auth API.
3. Organization Plugin Integration (Multi-Tenancy)
The Organization Plugin manages multi-tenant boundaries. The Go backend leverages themembers and organizations tables to enforce tenant isolation.
Member Roles
Themembers table contains the user-to-organization mapping with a role field:
owner/admin: Full organization management.staff: Operational access (e.g., managing leave).viewer: Read-only observation.
Tenant Isolation
Authorization logic in Go ensures that theorganizationId from the user’s JWT matches the data context.
4. Permission Resolution Flow
Low-latency authorization is achieved through a multi-tiered lookup:- JWT Claims: Fast check of the
orgRoleandorganizationIdclaims. - Redis Cache: If mapping logic changes or claims are missing, query Redis (5m TTL).
- PostgreSQL: On cache miss, perform a direct indexed query on the
memberstable.
5. Consistency via NATS
Since Go is read-only, it must be notified when a user’s role or membership changes in the Bun backend. We use NATS for real-time cache invalidation:- Subject:
member.role.changed,member.removed - Action: The Go
MemberRoleChangeConsumerinvalidates the local Redis cache keyperm:<userId>:<orgId>. - Result: The next Go request triggers a fresh database query, ensuring sub-second consistency across microservices.
6. Performance Benchmarks
To ensure high-performance lookups, the following indexes are strictly maintained:idx_users_roleidx_members_user_org(Compound index for membership checks)idx_members_organization_id_role(For listing org members)