The Power of Interface-Based Design
In our refactored architecture, theUserRepository and OrganizationRepository are read-only interfaces. The business logic in Go microservices uses these interfaces to retrieve identity data, without knowing—or caring—that the data is managed by the Better Auth service on the Bun monolith.
Core Pattern: Direct PostgreSQL Queries
We have eliminated distributed data synchronization (NATS user sync) in favor of direct, read-only queries to the Better Auth PostgreSQL tables. This ensures absolute consistency and simplifies the system architecture.1. User Repository Implementation
TheUserRepository maps the Better Auth users table to our local domain entities using GORM.
- ✅ Absolute Consistency: No lag between user creation in Bun and availability in Go.
- ✅ Infrastructure Simplicity: No NATS topics or event handlers for user synchronization.
- ✅ Performance: Direct DB queries with optimized indexes are extremely fast.
2. Organization & Membership Joins
To retrieve organization context, we join theorganizations and members tables.
3. Performance Optimization with Redis
While direct DB queries are fast, we use a Permission Cache for frequently checked authorization rules. This layer wraps our database-backed permission service. Use Case: Checkingleave:approve permission on every API request.
Strategy:
- JWT Validation (Stateless): Signatures verified locally.
- Permission Check: Resolution from
memberstable role field. - Caching: Store resolved permission arrays in Redis with a 5-minute TTL.
Comparison: Old vs. New Architecture
| Feature | Old (Clerk + NATS Sync) | New (Better Auth + Direct Query) |
|---|---|---|
| Source of Truth | Clerk (Cloud) | Better Auth (Local PostgreSQL) |
| Consistency | Eventual (Sync Lag) | Absolute (Direct DB) |
| Go Responsibility | Write + Read | Read-Only |
| Tables | user_sync (Local) | users, members (Shared) |
| Complexity | High (Event handling) | Low (Standard SQL) |
Implementation Rules
- Read-Only: No
Create,Update, orDeletemethods in Go user/org repositories. - Plural Naming: Always use plural table names (
users,members,organizations,accounts,sessions). - Write Forwarding: If a Go service needs to trigger a user mutation, it must call the Better Auth HTTP API or emit a high-level business event that the Bun monolith consumes.
- Interface Isolation: Keep domain entities isolated from the database schema using tags and mapping logic in the repository layer.