Subscription & Notification Platform

Year2026
TechnologyJava, Spring Boot, PostgreSQL, Kafka, SMTP, Redis, MCP, Flyway, 邮件订阅, 通知系统, 退订, 可靠投递

Architecture overview

A content event becomes a consent-aware email

Recipient selection and delivery are separate stages, with durable work between them.

Content event

1 / 5
Responsibility
A published-content event starts notification processing.
Data
Content identity and notification category.
Design boundary
Repeated events must not create uncontrolled duplicate work.

A subscription preference controls eligibility; delivery status records what happened next.

Project

Platform Case Study · Subscriber Engagement

Subscription and Notification Platform

Verified Preferences, Governed Unsubscribe and Reliable Delivery

This service combines subscriber lifecycle management, notification fan-out and email delivery into one bounded context. It supports verified subscription changes, stateful delivery retries and MCP-assisted unsubscribe without deleting subscriber history.

Repository Wiki

Explore the architecture and implementation with source-linked repository documentation.

AI-generated repository documentation; it may lag behind the code. Devin sign-in and workspace access may be required.

1. Product Responsibilities

  • Subscribe and verify ownership of an email address.
  • Manage topic preferences and web notification state.
  • Convert content events into recipient-specific delivery records.
  • Send concise article notifications with durable retry state.
  • Unsubscribe by status transition after email-code verification.

2. Architecture

flowchart LR User[Web user or MCP client] --> API[Subscription API] API --> Verify[Email verification service] Verify --> DB[(Subscribers + preferences)] Content{{Kafka content events}} --> Fanout[Recipient fan-out] Fanout --> DB DB --> Queue[Pending recipient queue] Queue --> Worker[Email dispatch worker] Worker --> Render[HTML + text renderer] Render --> SMTP[Email provider] Worker --> Delivery[(Delivery state + attempts)] Delivery --> DB

3. Subscriber State Model

stateDiagram-v2 [*] --> PENDING_VERIFICATION PENDING_VERIFICATION --> ACTIVE: valid verification code ACTIVE --> UNSUBSCRIBED: verified unsubscribe request UNSUBSCRIBED --> PENDING_VERIFICATION: resubscribe PENDING_VERIFICATION --> EXPIRED: code TTL elapsed

Unsubscribe never hard-deletes the subscriber. The service changes status, records the verified transition and retains non-sensitive delivery history for audit and suppression. A later resubscribe creates a new verification challenge rather than silently reactivating the address.

4. Secure Unsubscribe through MCP

  1. The agent selects subscription.request_unsubscribe_code from user intent.
  2. The gateway validates tool arguments, rate limits the address and stores only a hashed code.
  3. The notification service sends a short-lived code to the claimed email.
  4. The user supplies the code; the agent requests explicit confirmation if policy requires it.
  5. subscription.confirm_unsubscribe atomically transitions the subscriber to UNSUBSCRIBED.

Tool responses never disclose whether an unrelated address exists. Codes, provider credentials and authorization headers are redacted from Redis memory and audit payloads.

5. Notification Fan-out

A content event does not send email directly. The fan-out stage evaluates subscriber status and topic preferences, then creates one idempotent recipient record per eligible subscriber. The unique event/subscriber/channel key makes Kafka redelivery safe.

6. Delivery State Machine

StateMeaningNext action
PENDINGEligible and ready to claimWorker claims a bounded batch
PROCESSINGLeased by one workerRender and call provider
SENTProvider accepted deliveryTerminal
RETRYTransient provider failure60–960 second exponential backoff
FAILEDRetry budget exhaustedOperator review or replay
SKIPPEDPreference or status no longer allows deliveryTerminal

7. Email Content Design

Notification email is intentionally not the entire article. It contains the title, a bounded summary, topic metadata and one canonical call to action. This keeps messages scannable, reduces rendering risk and returns readers to the source-of-truth page.

8. Reliability and Operations

  • Database claiming prevents two workers from sending the same recipient record.
  • Idempotency keys protect subscribe, verification and MCP action retries.
  • Metrics cover pending age, provider latency, retry rate and permanent failure rate.
  • Provider outages do not block content publishing or subscriber preference changes.

9. Engineering Outcome

The combined boundary keeps consent, preferences and delivery decisions consistent while separating asynchronous email work from synchronous APIs. The result is auditable, retryable and safe to expose through both the website and governed MCP tools.