Source:
ocean/docs/adr/008-simplified-graphql-provisioning.md| ✏️ Edit on GitHub
ADR-008: Simplified GraphQL Provisioning
Status
Accepted
Context
Our current user signup and organization provisioning flow has become increasingly complex:
- Multiple database triggers and webhooks coordinate provisioning
- Complex JSONB status tracking in the
provisioning_statuscolumn - Frontend needs to poll for status updates and show progress UI
- Race conditions between email verification and provisioning completion
- Difficult to debug failures across multiple async processes
- Poor user experience with loading screens and status indicators
The existing flow involves:
- User signs up via Supabase Auth
- Database trigger creates organization
- Multiple Edge Functions handle provisioning (Stripe, Neon, etc.)
- Frontend polls for status updates
- Complex error handling and retry logic spread across services
Decision
We will implement a simplified "fire-and-forget" provisioning model where:
- Single GraphQL mutation handles signup and initiates provisioning
- Background provisioning runs while user verifies email (30s-2min window)
- No status tracking UI - provisioning completes transparently
- Simple boolean flags replace complex JSONB status objects
- Automatic retry on login if resources aren't ready
Implementation Details
GraphQL Schema
mutation SignUpUser($input: SignUpInput!) {
signUp(input: $input) {
success
message
}
}
input SignUpInput {
email: String!
firstName: String!
lastName: String!
organizationName: String!
industry: String!
dataRegion: String!
}
Provisioning Flow
async function signUp(input) {
// 1. Create user synchronously
const user = await supabase.auth.signUp({
email,
metadata: { ...input },
})
// 2. Get organization (created by trigger)
const org = await getOrganizationByUserId(user.id)
// 3. Fire-and-forget provisioning
provisionResources(org.id, user).catch(logError)
// 4. Return immediately
return { success: true, message: 'Check email' }
}
Database Schema Changes
-- Remove complex tracking
ALTER TABLE organizations
DROP COLUMN provisioning_status,
DROP COLUMN provisioning_started_at,
DROP COLUMN provisioning_completed_at;
-- Add simple flags
ALTER TABLE organizations
ADD COLUMN neon_database_ready boolean DEFAULT false;
Consequences
Positive
- Dramatically simpler architecture - removed 200+ lines of status tracking code
- Better user experience - no loading screens or progress indicators
- More reliable - fewer moving parts and race conditions
- Easier to debug - provisioning logic consolidated in one place
- Faster perceived performance - users can proceed immediately
- Reduced frontend complexity - no polling or status UI components
Negative
- Less visibility during provisioning - no real-time status updates
- Potential confusion if provisioning fails silently
- Harder to track provisioning metrics without detailed status
- May need to handle edge cases where user logs in before provisioning completes
Mitigations
- Health checks on login automatically retry failed provisioning
- Comprehensive logging via Sentry for debugging
- Provisioning events table retained for audit trail
- 30s-2min email verification window provides ample provisioning time
Alternatives Considered
1. Keep Complex Status Tracking
- Pros: Full visibility, detailed progress tracking
- Cons: Complex implementation, poor UX, maintenance burden
- Rejected: Complexity outweighs benefits for our use case
2. Synchronous Provisioning
- Pros: Guaranteed resources ready on signup
- Cons: 10-30 second signup time, poor UX, timeout risks
- Rejected: Unacceptable user experience
3. Queue-Based Provisioning
- Pros: Reliable, retryable, observable
- Cons: Additional infrastructure (Redis/RabbitMQ), complexity
- Rejected: Over-engineered for our scale
4. Lazy Provisioning
- Pros: Provision only when needed
- Cons: Delays on first use, complex coordination
- Rejected: Poor first-use experience
Implementation Plan
Phase 1: Backend (Complete)
- ✅ GraphQL schema updates
- ✅ SignUp resolver implementation
- ✅ Background provisioning logic
- ✅ Database schema simplification
- ✅ Health check system
Phase 2: Frontend (Pending)
- Update signup form to use GraphQL mutation
- Remove status tracking UI components
- Update success messaging
Phase 3: Production (Pending)
- Configure production API keys (Stripe, Neon)
- Deploy database migrations
- Monitor provisioning success rates
Metrics for Success
- Signup completion rate > 95%
- Provisioning success rate > 99%
- Time to fully provisioned < 2 minutes
- Support tickets related to provisioning < 1%
References
- Simplified GraphQL Provisioning Plan
- Implementation Details
- Original Complex Provisioning ADR
- GraphQL Edge Function
Decision Makers
- Engineering Team
- Product Team
Date
2025-08-06