ADR-006: Separate Notification Service
Status
Accepted
Context
Multiple services need to send notifications (welcome emails, verification alerts, subscription reminders). We needed to decide:
- Embedded in each service: Simple but duplicated logic
- Shared package: No independent scaling
- Separate service: Independent, scalable, single responsibility
Decision
We will create a separate Notification Service for email/SMS notifications.
Rationale
Why Separate Service?
| Reason | Explanation |
|---|---|
| Cross-cutting concern | Identity, Admin, Subscription, Prescription all need notifications |
| External integrations | Email provider (SES), SMS gateway (Twilio) |
| Retry logic | Failed notifications need retries, backoff |
| Template management | Email/SMS templates with variables |
| Rate limiting | Provider-specific rate limits |
| Scheduling | Trial ending reminders, subscription renewals |
| Audit trail | Track what was sent, when, delivery status |
Event-Driven Integration
Other services publish events → Notification service consumes and sends:
Identity Service Notification Service
│ │
│── user.registered ──────>│── Welcome email
│── doctor.profile.created │── Verification pending email
│ │
Admin Service │
│ │
│── doctor.verified ──────>│── Congratulations email
│── doctor.rejected ──────>│── Rejection email
│ │
Organization Service │
│ │
│── member.invited ────────│── Invitation email
│ │
Subscription Service │
│ │
│── subscription.canceled ─│── Confirmation email
│── subscription.trial.ending │── Reminder emailProvider Ports
go
type EmailProvider interface {
Send(ctx context.Context, to, subject, body string) error
}
type SMSProvider interface {
Send(ctx context.Context, to, message string) error
}Stub Providers for Development
go
// Logs to console instead of sending
emailProvider := email.NewStubEmailProvider()
smsProvider := sms.NewStubSMSProvider()Replace with real implementations (AWS SES, Twilio) when going to production.
Consequences
Positive
- Single responsibility for notifications
- Independent scaling
- Easy to swap providers
- Template management centralized
Negative
- Additional service to deploy
- Eventual consistency for notification delivery
Related Decisions
- ADR-003: Event-Driven Architecture