Add subcription feature

This commit is contained in:
Urtzi Alfaro
2026-01-13 22:22:38 +01:00
parent b931a5c45e
commit 6ddf608d37
61 changed files with 7915 additions and 1238 deletions

846
REARCHITECTURE_PROPOSAL.md Normal file
View File

@@ -0,0 +1,846 @@
# User Registration & Subscription Architecture Rearchitecture Proposal
## Executive Summary
This proposal outlines a comprehensive rearchitecture of the user registration, payment processing, and subscription management flow to address the current limitations and implement the requested multi-phase registration process.
## Current Architecture Analysis
### Current Flow Limitations
1. **Monolithic Registration Process**: The current flow combines user creation, payment processing, and subscription creation in a single step
2. **Tenant-Subscription Coupling**: Subscriptions are created and immediately linked to tenants during registration
3. **Payment Processing Timing**: Payment is processed before user creation is complete
4. **Onboarding Complexity**: The onboarding flow assumes immediate tenant creation with subscription
### Key Components Analysis
#### Frontend Components
- `RegisterForm.tsx`: Multi-step form handling basic info, subscription selection, and payment
- `PaymentForm.tsx`: Stripe payment processing component
- `RegisterTenantStep.tsx`: Tenant creation during onboarding
#### Backend Services
- **Auth Service**: User creation, authentication, and onboarding progress tracking
- **Tenant Service**: Tenant creation, subscription management, and payment processing
- **Shared Clients**: Inter-service communication between auth and tenant services
#### Current Data Flow
```mermaid
graph TD
A[Frontend RegisterForm] -->|User Data + Payment| B[Auth Service Register]
B -->|Create User| C[User Created]
B -->|Call Tenant Service| D[Tenant Service Payment Customer]
D -->|Create Payment Customer| E[Payment Customer Created]
C -->|Return Tokens| F[User Authenticated]
F -->|Onboarding| G[RegisterTenantStep]
G -->|Create Tenant + Subscription| H[Tenant Service Create Tenant]
H -->|Create Subscription| I[Subscription Created]
```
## Proposed Architecture
### New Multi-Phase Registration Flow
```mermaid
graph TD
subgraph Frontend
A1[Basic Info Form] -->|Email + Password| A2[Subscription Selection]
A2 -->|Plan + Billing Cycle| A3[Payment Form]
A3 -->|Payment Method| A4[Process Payment]
end
subgraph Backend Services
A4 -->|User Data + Payment| B1[Auth Service Register]
B1 -->|Create User| B2[User Created with Payment ID]
B2 -->|Call Tenant Service| B3[Tenant Service Create Subscription]
B3 -->|Create Subscription| B4[Subscription Created]
B4 -->|Return Subscription ID| B2
B2 -->|Return Auth Tokens| A4
end
subgraph Onboarding
A4 -->|Success| C1[Onboarding Flow]
C1 -->|Tenant Creation| C2[RegisterTenantStep]
C2 -->|Tenant Data| C3[Tenant Service Create Tenant]
C3 -->|Link Subscription| C4[Link Subscription to Tenant]
C4 -->|Complete| C5[Onboarding Complete]
end
```
### Detailed Component Changes
#### 1. Frontend Changes
**RegisterForm.tsx Modifications:**
- **Phase 1**: Collect only email and password (basic info)
- **Phase 2**: Plan selection with billing cycle options
- **Phase 3**: Payment form with address and card details
- **Payment Processing**: Call new backend endpoint with complete registration data
**New Payment Flow:**
```typescript
// Current: handleRegistrationSubmit calls authService.register directly
// New: handleRegistrationSubmit calls new registration endpoint
const handleRegistrationSubmit = async (paymentMethodId?: string) => {
try {
const registrationData = {
email: formData.email,
password: formData.password,
full_name: formData.full_name,
subscription_plan: selectedPlan,
billing_cycle: billingCycle,
payment_method_id: paymentMethodId,
coupon_code: isPilot ? couponCode : undefined,
// Address and billing info
address: billingAddress,
postal_code: billingPostalCode,
city: billingCity,
country: billingCountry
};
// Call new registration endpoint
const response = await authService.registerWithSubscription(registrationData);
// Handle success and redirect to onboarding
onSuccess?.();
} catch (err) {
// Handle errors
}
};
```
#### 2. Auth Service Changes
**New Registration Endpoint:**
```python
@router.post("/api/v1/auth/register-with-subscription")
async def register_with_subscription(
user_data: UserRegistrationWithSubscription,
auth_service: EnhancedAuthService = Depends(get_auth_service)
):
"""Register user and create subscription in one call"""
# Step 1: Create user
user = await auth_service.register_user(user_data)
# Step 2: Create payment customer via tenant service
payment_result = await auth_service.create_payment_customer_via_tenant_service(
user_data,
user_data.payment_method_id
)
# Step 3: Create subscription via tenant service
subscription_result = await auth_service.create_subscription_via_tenant_service(
user.id,
user_data.subscription_plan,
user_data.payment_method_id,
user_data.billing_cycle,
user_data.coupon_code
)
# Step 4: Store subscription ID in user's onboarding progress
await auth_service.save_subscription_to_onboarding_progress(
user.id,
subscription_result.subscription_id,
user_data
)
return {
**user,
subscription_id: subscription_result.subscription_id
}
```
**Enhanced Auth Service Methods:**
```python
class EnhancedAuthService:
async def create_subscription_via_tenant_service(
self,
user_id: str,
plan_id: str,
payment_method_id: str,
billing_cycle: str,
coupon_code: Optional[str] = None
) -> Dict[str, Any]:
"""Create subscription via tenant service during registration"""
try:
from shared.clients.tenant_client import TenantServiceClient
from app.core.config import settings
tenant_client = TenantServiceClient(settings)
# Prepare user data for tenant service
user_data = await self.get_user_data_for_tenant_service(user_id)
# Call tenant service to create subscription
result = await tenant_client.create_subscription_for_registration(
user_data=user_data,
plan_id=plan_id,
payment_method_id=payment_method_id,
billing_cycle=billing_cycle,
coupon_code=coupon_code
)
return result
except Exception as e:
logger.error("Failed to create subscription via tenant service",
user_id=user_id, error=str(e))
raise
async def save_subscription_to_onboarding_progress(
self,
user_id: str,
subscription_id: str,
registration_data: Dict[str, Any]
):
"""Store subscription info in onboarding progress for later tenant linking"""
try:
# Get or create onboarding progress
progress = await self.onboarding_repo.get_user_progress(user_id)
if not progress:
progress = await self.onboarding_repo.create_user_progress(user_id)
# Store subscription data in user_registered step
step_data = {
"subscription_id": subscription_id,
"subscription_plan": registration_data.subscription_plan,
"billing_cycle": registration_data.billing_cycle,
"coupon_code": registration_data.coupon_code,
"payment_method_id": registration_data.payment_method_id,
"payment_customer_id": registration_data.payment_customer_id,
"created_at": datetime.now(timezone.utc).isoformat(),
"status": "pending_tenant_linking"
}
await self.onboarding_repo.upsert_user_step(
user_id=user_id,
step_name="user_registered",
completed=True,
step_data=step_data
)
logger.info("Subscription data saved to onboarding progress",
user_id=user_id,
subscription_id=subscription_id)
except Exception as e:
logger.error("Failed to save subscription to onboarding progress",
user_id=user_id, error=str(e))
raise
```
#### 3. Tenant Service Changes
**New Subscription Creation Endpoint:**
```python
@router.post("/api/v1/subscriptions/create-for-registration")
async def create_subscription_for_registration(
user_data: Dict[str, Any],
plan_id: str = Query(...),
payment_method_id: str = Query(...),
billing_cycle: str = Query("monthly"),
coupon_code: Optional[str] = Query(None),
payment_service: PaymentService = Depends(get_payment_service),
db: AsyncSession = Depends(get_db)
):
"""
Create subscription during user registration (before tenant creation)
This endpoint creates a subscription that is not yet linked to any tenant.
The subscription will be linked to a tenant during the onboarding flow.
"""
try:
# Use orchestration service for complete workflow
orchestration_service = SubscriptionOrchestrationService(db)
# Create subscription without tenant_id (tenant-independent subscription)
result = await orchestration_service.create_tenant_independent_subscription(
user_data,
plan_id,
payment_method_id,
billing_cycle,
coupon_code
)
logger.info("Tenant-independent subscription created for registration",
user_id=user_data.get('user_id'),
subscription_id=result["subscription_id"])
return {
"success": True,
"subscription_id": result["subscription_id"],
"customer_id": result["customer_id"],
"status": result["status"],
"plan": result["plan"],
"billing_cycle": result["billing_cycle"]
}
except Exception as e:
logger.error("Failed to create tenant-independent subscription",
error=str(e),
user_id=user_data.get('user_id'))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to create subscription"
)
```
**Enhanced Subscription Orchestration Service:**
```python
class SubscriptionOrchestrationService:
async def create_tenant_independent_subscription(
self,
user_data: Dict[str, Any],
plan_id: str,
payment_method_id: str,
billing_cycle: str = "monthly",
coupon_code: Optional[str] = None
) -> Dict[str, Any]:
"""
Create a subscription that is not linked to any tenant yet
This subscription will be linked to a tenant during onboarding
when the user creates their bakery/tenant.
"""
try:
logger.info("Creating tenant-independent subscription",
user_id=user_data.get('user_id'),
plan_id=plan_id)
# Step 1: Create customer in payment provider
customer = await self.payment_service.create_customer(user_data)
# Step 2: Handle coupon logic
trial_period_days = 0
coupon_discount = None
if coupon_code:
coupon_service = CouponService(self.db_session)
success, discount_applied, error = await coupon_service.redeem_coupon(
coupon_code,
None, # No tenant_id yet
base_trial_days=0
)
if success and discount_applied:
coupon_discount = discount_applied
trial_period_days = discount_applied.get("total_trial_days", 0)
# Step 3: Create subscription in payment provider
stripe_subscription = await self.payment_service.create_payment_subscription(
customer.id,
plan_id,
payment_method_id,
trial_period_days if trial_period_days > 0 else None,
billing_cycle
)
# Step 4: Create local subscription record WITHOUT tenant_id
subscription_record = await self.subscription_service.create_tenant_independent_subscription_record(
stripe_subscription.id,
customer.id,
plan_id,
stripe_subscription.status,
stripe_subscription.current_period_start,
stripe_subscription.current_period_end,
trial_period_days if trial_period_days > 0 else None,
billing_cycle,
user_data.get('user_id')
)
# Step 5: Store subscription in pending_tenant_linking state
await self.subscription_service.mark_subscription_as_pending_tenant_linking(
subscription_record.id,
user_data.get('user_id')
)
return {
"success": True,
"customer_id": customer.id,
"subscription_id": stripe_subscription.id,
"status": stripe_subscription.status,
"plan": plan_id,
"billing_cycle": billing_cycle,
"trial_period_days": trial_period_days,
"current_period_end": stripe_subscription.current_period_end.isoformat(),
"coupon_applied": bool(coupon_discount),
"user_id": user_data.get('user_id')
}
except Exception as e:
logger.error("Failed to create tenant-independent subscription",
error=str(e),
user_id=user_data.get('user_id'))
raise
```
**New Subscription Service Methods:**
```python
class SubscriptionService:
async def create_tenant_independent_subscription_record(
self,
subscription_id: str,
customer_id: str,
plan: str,
status: str,
current_period_start: datetime,
current_period_end: datetime,
trial_period_days: Optional[int] = None,
billing_cycle: str = "monthly",
user_id: Optional[str] = None
) -> Subscription:
"""Create subscription record without tenant_id"""
try:
subscription_data = {
"subscription_id": subscription_id,
"customer_id": customer_id,
"plan": plan,
"status": status,
"current_period_start": current_period_start,
"current_period_end": current_period_end,
"trial_period_days": trial_period_days,
"billing_cycle": billing_cycle,
"user_id": user_id,
"tenant_id": None, # No tenant linked yet
"is_tenant_linked": False,
"created_at": datetime.now(timezone.utc),
"updated_at": datetime.now(timezone.utc)
}
subscription = await self.subscription_repo.create(subscription_data)
logger.info("Tenant-independent subscription record created",
subscription_id=subscription.id,
user_id=user_id)
return subscription
except Exception as e:
logger.error("Failed to create tenant-independent subscription record",
error=str(e))
raise
async def mark_subscription_as_pending_tenant_linking(
self,
subscription_id: str,
user_id: str
):
"""Mark subscription as pending tenant linking"""
try:
await self.subscription_repo.update(
subscription_id,
{
"status": "pending_tenant_linking",
"tenant_linking_status": "pending",
"user_id": user_id
}
)
logger.info("Subscription marked as pending tenant linking",
subscription_id=subscription_id,
user_id=user_id)
except Exception as e:
logger.error("Failed to mark subscription as pending tenant linking",
error=str(e),
subscription_id=subscription_id)
raise
```
#### 4. Onboarding Flow Changes
**Enhanced RegisterTenantStep:**
```typescript
// When tenant is created, link the pending subscription
const handleSubmit = async () => {
if (!validateForm()) {
return;
}
try {
let tenant;
if (tenantId) {
// Update existing tenant
const updateData: TenantUpdate = { ... };
tenant = await updateTenant.mutateAsync({ tenantId, updateData });
} else {
// Create new tenant and link subscription
const registrationData: BakeryRegistrationWithSubscription = {
...formData,
// Include subscription linking data from onboarding progress
subscription_id: wizardContext.state.subscriptionId,
link_existing_subscription: true
};
tenant = await registerBakery.mutateAsync(registrationData);
}
// Continue with onboarding
onComplete({ tenant, tenantId: tenant.id });
} catch (error) {
console.error('Error registering bakery:', error);
setErrors({ submit: t('onboarding:steps.tenant_registration.errors.register') });
}
};
```
**Enhanced Tenant Creation Endpoint:**
```python
@router.post(route_builder.build_base_route("register", include_tenant_prefix=False))
async def register_bakery(
bakery_data: BakeryRegistrationWithSubscription,
current_user: Dict[str, Any] = Depends(get_current_user_dep),
tenant_service: EnhancedTenantService = Depends(get_enhanced_tenant_service),
db: AsyncSession = Depends(get_db)
):
"""Register a new bakery/tenant with subscription linking"""
try:
// Create tenant first
result = await tenant_service.create_bakery(bakery_data, current_user["user_id"])
tenant_id = result["tenant_id"]
// Check if we need to link an existing subscription
if bakery_data.link_existing_subscription and bakery_data.subscription_id:
// Link the pending subscription to this tenant
subscription_result = await tenant_service.link_subscription_to_tenant(
tenant_id,
bakery_data.subscription_id,
current_user["user_id"]
)
logger.info("Subscription linked to tenant during registration",
tenant_id=tenant_id,
subscription_id=bakery_data.subscription_id)
else:
// Fallback to current behavior for backward compatibility
// Create new subscription if needed
pass
return result
except Exception as e:
logger.error("Failed to register bakery with subscription linking",
error=str(e),
user_id=current_user["user_id"])
raise
```
**New Tenant Service Method for Subscription Linking:**
```python
class EnhancedTenantService:
async def link_subscription_to_tenant(
self,
tenant_id: str,
subscription_id: str,
user_id: str
) -> Dict[str, Any]:
"""Link a pending subscription to a tenant"""
try:
async with self.database_manager.get_session() as db_session:
async with UnitOfWork(db_session) as uow:
# Register repositories
subscription_repo = uow.register_repository(
"subscriptions", SubscriptionRepository, Subscription
)
tenant_repo = uow.register_repository(
"tenants", TenantRepository, Tenant
)
# Get the subscription
subscription = await subscription_repo.get_by_id(subscription_id)
if not subscription:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Subscription not found"
)
# Verify subscription is in pending_tenant_linking state
if subscription.tenant_linking_status != "pending":
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Subscription is not in pending tenant linking state"
)
# Verify subscription belongs to this user
if subscription.user_id != user_id:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Subscription does not belong to this user"
)
# Update subscription with tenant_id
update_data = {
"tenant_id": tenant_id,
"is_tenant_linked": True,
"tenant_linking_status": "completed",
"linked_at": datetime.now(timezone.utc)
}
await subscription_repo.update(subscription_id, update_data)
# Update tenant with subscription information
tenant_update = {
"stripe_customer_id": subscription.customer_id,
"subscription_status": subscription.status,
"subscription_plan": subscription.plan,
"subscription_tier": subscription.plan,
"billing_cycle": subscription.billing_cycle,
"trial_period_days": subscription.trial_period_days
}
await tenant_repo.update_tenant(tenant_id, tenant_update)
# Commit transaction
await uow.commit()
logger.info("Subscription successfully linked to tenant",
tenant_id=tenant_id,
subscription_id=subscription_id,
user_id=user_id)
return {
"success": True,
"tenant_id": tenant_id,
"subscription_id": subscription_id,
"status": "linked"
}
except Exception as e:
logger.error("Failed to link subscription to tenant",
error=str(e),
tenant_id=tenant_id,
subscription_id=subscription_id,
user_id=user_id)
raise
```
## Database Schema Changes
### New Subscription Table Structure
```sql
-- Add new columns to subscriptions table
ALTER TABLE subscriptions ADD COLUMN IF NOT EXISTS user_id UUID;
ALTER TABLE subscriptions ADD COLUMN IF NOT EXISTS is_tenant_linked BOOLEAN DEFAULT FALSE;
ALTER TABLE subscriptions ADD COLUMN IF NOT EXISTS tenant_linking_status VARCHAR(50);
ALTER TABLE subscriptions ADD COLUMN IF NOT EXISTS linked_at TIMESTAMP;
-- Add index for user-based subscription queries
CREATE INDEX IF NOT EXISTS idx_subscriptions_user_id ON subscriptions(user_id);
CREATE INDEX IF NOT EXISTS idx_subscriptions_linking_status ON subscriptions(tenant_linking_status);
-- Add constraint to ensure tenant_id is NULL when not linked
ALTER TABLE subscriptions ADD CONSTRAINT chk_tenant_linking
CHECK ((is_tenant_linked = FALSE AND tenant_id IS NULL) OR
(is_tenant_linked = TRUE AND tenant_id IS NOT NULL));
```
### Onboarding Progress Data Structure
```json
{
"user_id": "user-uuid",
"current_step": "user_registered",
"steps": [
{
"step_name": "user_registered",
"completed": true,
"completed_at": "2025-10-15T10:30:00Z",
"data": {
"subscription_id": "sub-uuid",
"subscription_plan": "professional",
"billing_cycle": "yearly",
"coupon_code": "PILOT2025",
"payment_method_id": "pm-123",
"payment_customer_id": "cus-456",
"status": "pending_tenant_linking",
"created_at": "2025-10-15T10:30:00Z"
}
}
]
}
```
## Error Handling & Recovery
### Error Scenarios and Recovery Strategies
1. **Payment Processing Failure**
- **Scenario**: Payment fails during registration
- **Recovery**: Rollback user creation, show error to user, allow retry
- **Implementation**: Transaction management in auth service
2. **Subscription Creation Failure**
- **Scenario**: Subscription creation fails after user creation
- **Recovery**: User created but marked as "registration_incomplete", allow retry in onboarding
- **Implementation**: Store registration state, provide recovery endpoint
3. **Tenant Linking Failure**
- **Scenario**: Tenant creation succeeds but subscription linking fails
- **Recovery**: Tenant created with default trial subscription, manual linking available
- **Implementation**: Fallback to current behavior, admin notification
4. **Orphaned Subscriptions**
- **Scenario**: User registers but never completes onboarding
- **Recovery**: Cleanup task to cancel subscriptions after 30 days
- **Implementation**: Background job to monitor pending subscriptions
### Monitoring and Alerts
```python
# Subscription linking monitoring
class SubscriptionMonitoringService:
async def monitor_pending_subscriptions(self):
"""Monitor subscriptions pending tenant linking"""
pending_subscriptions = await self.subscription_repo.get_pending_tenant_linking()
for subscription in pending_subscriptions:
created_days_ago = (datetime.now(timezone.utc) - subscription.created_at).days
if created_days_ago > 30:
# Cancel subscription and notify user
await self.cancel_orphaned_subscription(subscription.id)
await self.notify_user_about_cancellation(subscription.user_id)
elif created_days_ago > 7:
# Send reminder to complete onboarding
await self.send_onboarding_reminder(subscription.user_id)
```
## Migration Strategy
### Phase 1: Backend Implementation
1. **Database Migration**: Add new columns to subscriptions table
2. **Auth Service Updates**: Implement new registration endpoint
3. **Tenant Service Updates**: Implement tenant-independent subscription creation
4. **Shared Clients**: Update inter-service communication
### Phase 2: Frontend Implementation
1. **Registration Form**: Update to collect billing address
2. **Payment Flow**: Integrate with new backend endpoints
3. **Onboarding Flow**: Add subscription linking logic
### Phase 3: Testing and Validation
1. **Unit Tests**: Verify individual component behavior
2. **Integration Tests**: Test service-to-service communication
3. **End-to-End Tests**: Validate complete user journey
4. **Load Testing**: Ensure performance under load
### Phase 4: Deployment and Rollout
1. **Feature Flags**: Enable gradual rollout
2. **A/B Testing**: Compare with existing flow
3. **Monitoring**: Track key metrics and errors
4. **Rollback Plan**: Prepare for quick rollback if needed
## Benefits of the New Architecture
### 1. Improved User Experience
- **Clear Separation of Concerns**: Users understand each step of the process
- **Progressive Commitment**: Users can complete registration without immediate tenant creation
- **Flexible Onboarding**: Users can explore the platform before committing to a specific bakery
### 2. Better Error Handling
- **Isolated Failure Points**: Failures in one step don't cascade to others
- **Recovery Paths**: Clear recovery mechanisms for each failure scenario
- **Graceful Degradation**: System remains functional even with partial failures
### 3. Enhanced Business Flexibility
- **Multi-Tenant Support**: Users can create multiple tenants with the same subscription
- **Subscription Portability**: Subscriptions can be moved between tenants
- **Trial Management**: Better control over trial periods and conversions
### 4. Improved Security
- **Data Isolation**: Sensitive payment data handled separately from user data
- **Audit Trails**: Clear tracking of subscription lifecycle
- **Compliance**: Better support for GDPR and payment industry standards
### 5. Scalability
- **Microservice Alignment**: Better separation between auth and tenant services
- **Independent Scaling**: Services can be scaled independently
- **Future Extensibility**: Easier to add new features and integrations
## Implementation Timeline
| Phase | Duration | Key Activities |
|-------|----------|----------------|
| 1. Analysis & Design | 2 weeks | Architecture review, technical design, stakeholder approval |
| 2. Backend Implementation | 4 weeks | Database changes, service updates, API development |
| 3. Frontend Implementation | 3 weeks | Form updates, payment integration, onboarding changes |
| 4. Testing & QA | 3 weeks | Unit tests, integration tests, E2E tests, performance testing |
| 5. Deployment & Rollout | 2 weeks | Staging deployment, production rollout, monitoring setup |
| 6. Post-Launch | Ongoing | Bug fixes, performance optimization, feature enhancements |
## Risks and Mitigation
### Technical Risks
1. **Data Consistency**: Risk of inconsistent state between services
- *Mitigation*: Strong transaction management, idempotent operations, reconciliation jobs
2. **Performance Impact**: Additional service calls may impact performance
- *Mitigation*: Caching, async processing, performance optimization
3. **Complexity Increase**: More moving parts increase system complexity
- *Mitigation*: Clear documentation, comprehensive monitoring, gradual rollout
### Business Risks
1. **User Confusion**: Multi-step process may confuse some users
- *Mitigation*: Clear UI guidance, progress indicators, help documentation
2. **Conversion Impact**: Additional steps may reduce conversion rates
- *Mitigation*: A/B testing, user feedback, iterative improvements
3. **Support Burden**: New flow may require additional support
- *Mitigation*: Comprehensive documentation, self-service recovery, support training
## Success Metrics
### Key Performance Indicators
1. **Registration Completion Rate**: Percentage of users completing registration
2. **Onboarding Completion Rate**: Percentage of users completing onboarding
3. **Error Rates**: Frequency of errors in each step
4. **Conversion Rates**: Percentage of visitors becoming paying customers
5. **User Satisfaction**: Feedback and ratings from users
### Monitoring Dashboard
```
Registration Funnel:
- Step 1 (Basic Info): 100%
- Step 2 (Plan Selection): 85%
- Step 3 (Payment): 75%
- Onboarding Completion: 60%
Error Metrics:
- Registration Errors: < 1%
- Payment Errors: < 2%
- Subscription Linking Errors: < 0.5%
Performance Metrics:
- Registration Time: < 5s
- Payment Processing Time: < 3s
- Tenant Creation Time: < 2s
```
## Conclusion
This rearchitecture proposal addresses the current limitations by implementing a clear separation between user registration, payment processing, and tenant creation. The new multi-phase approach provides better user experience, improved error handling, and enhanced business flexibility while maintaining backward compatibility and providing clear migration paths.
The proposed solution aligns with modern microservice architectures and provides a solid foundation for future growth and feature enhancements.