Расскажи про свой опыт проектирования сервиса с нуля
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Опыт проектирования сервиса с нуля: Payment Gateway для e-commerce
Я хотел бы рассказать о реальном проекте, который я проектировал с нуля в 2022 году — Payment Gateway для e-commerce платформы. Это был greenfield проект, где я отвечал за архитектуру и анализ на всех этапах.
Контекст и требования
Бизнес-требования:
- Обработка 50K+ платежей в день
- Поддержка 15+ платёжных методов (карты, e-wallets, bank transfers)
- PCI-DSS compliance (уровень 1)
- Real-time операции с <500ms latency
- Интеграция с существующей платформой (legacy monolith)
- Fallback на альтернативные провайдеры в случае сбоя
Non-functional requirements:
- Availability: 99.99% uptime
- Scalability: горизонтальное масштабирование
- Security: шифрование, audit trail, fraud detection
- Auditability: все операции логируются для compliance
Фаза 1: Анализ и проектирование архитектуры
Шаг 1: Исследование текущей ситуации
- Провел интервью с Product team, Finance, Engineering lead
- Изучил существующие платёжные системы конкурентов
- Проанализировал законодательство в каждой стране
- Провел risk assessment
Шаг 2: Определение граничных условий
Пиковая нагрузка: 50K платежей/день = ~1 платёж/сек (в среднем)
Пик: утро европейского дня = ~10 платежей/сек
Латентность:
- Клиент платит → ответ за <1сек
- Backend обрабатывает платёж → Провайдер за <500ms
Течность:
- Payment success rate должна быть >98%
- Fallback к backup провайдеру за <5сек
Шаг 3: Архитектурные решения
Выбрал микросервисную архитектуру с явными причинами:
Monolith
├── Users & Auth
├── Products & Catalog
├── Payment Service ← новое
├── Notifications
└── Analytics
Прежде я рассмотрел:
- Встроить в монолит → Сложно масштабировать, высокий risk
- Отдельный микросервис → ✅ Выбрано. Причины:
- Независимая scalability
- Отдельная deployment
- Изоляция PCI-DSS требований
- Возможность менять провайдеров без изменения монолита
Фаза 2: Детальное проектирование
1. Core entities и data model
-- Payment request (от клиента)
CREATE TABLE payment_requests (
id UUID PRIMARY KEY,
order_id UUID NOT NULL,
amount DECIMAL(12, 2) NOT NULL,
currency VARCHAR(3) NOT NULL,
payer_id UUID NOT NULL,
payment_method_id UUID NOT NULL,
status ENUM ('pending', 'processing', 'succeeded', 'failed', 'cancelled'),
created_at TIMESTAMPTZ NOT NULL,
expires_at TIMESTAMPTZ NOT NULL,
UNIQUE(order_id) -- One payment per order
);
-- Payment transaction (фактический платёж через провайдера)
CREATE TABLE payment_transactions (
id UUID PRIMARY KEY,
payment_request_id UUID NOT NULL REFERENCES payment_requests(id),
provider_id SMALLINT NOT NULL, -- Stripe, PayPal, etc
provider_transaction_id VARCHAR(255) NOT NULL,
status ENUM ('pending', 'succeeded', 'failed', 'declined'),
amount DECIMAL(12, 2) NOT NULL,
fee DECIMAL(12, 2) NOT NULL, -- Комиссия провайдера
retry_count SMALLINT DEFAULT 0,
error_code VARCHAR(100),
error_message TEXT,
response_time_ms INT,
created_at TIMESTAMPTZ NOT NULL,
updated_at TIMESTAMPTZ NOT NULL,
FOREIGN KEY (payment_request_id) REFERENCES payment_requests(id)
);
-- Audit log для compliance
CREATE TABLE payment_audit_log (
id BIGSERIAL PRIMARY KEY,
payment_request_id UUID NOT NULL,
action VARCHAR(50) NOT NULL, -- 'created', 'processing', 'succeeded', etc
actor VARCHAR(100) NOT NULL, -- 'system', 'user_id', 'provider'
details JSONB,
ip_address INET,
user_agent TEXT,
created_at TIMESTAMPTZ NOT NULL,
INDEX (payment_request_id, created_at)
);
2. API контракты
Client → Load Balancer → Payment Service → Payment Processors
REST API endpoints:
1. POST /api/v1/payments
Request: {
"order_id": "uuid",
"amount": 99.99,
"currency": "USD",
"payment_method_id": "uuid",
"customer_id": "uuid"
}
Response: {
"id": "uuid",
"status": "processing",
"redirect_url": "https://provider.com/verify?token=xxx"
}
Status: 201 Created
2. GET /api/v1/payments/{id}
Response: {
"id": "uuid",
"status": "succeeded",
"amount": 99.99,
"provider": "stripe",
"provider_transaction_id": "ch_xxx"
}
3. POST /api/v1/payments/{id}/retry
(Retry failed payment with fallback provider)
4. POST /api/v1/webhooks/stripe
(Webhook от провайдера)
Фаза 3: Обработка платежей (Flow)
Синхронный flow (для быстрых провайдеров)
1. Client initiates payment
↓
2. Payment Service validates input
↓
3. Create payment_request with status='pending'
↓
4. Call Payment Provider (Stripe, PayPal)
↓
5. If success (< 500ms):
- Update payment_request to 'succeeded'
- Send notification
- Return 200 OK
6. If timeout/error:
- Try fallback provider
- If fallback succeeds → same as 5
- If all fail → status='failed', return 402 Payment Required
Асинхронный flow (для 3D Secure, redirects)
1. Client initiates payment
↓
2. Payment Service creates payment_request
↓
3. Generate redirect_url с verification token
↓
4. Client is redirected to provider (iframe или новый window)
↓
5. Client завершает 3D Secure
↓
6. Provider redirects back to us с callback
↓
7. Webhook handler обновляет status
↓
8. Client polling GET /payments/{id} → status='succeeded'
Фаза 4: Resilience и Fallback
Circuit breaker pattern:
# Если Stripe downtime > 1 минуты:
# - Все новые платежи идут на PayPal
# - Старые platежи retry автоматически
STRIPE_FAILURE_THRESHOLD = 5 # failures per minute
FAILURE_WINDOW = 60 # seconds
if stripe_failures_in_window > THRESHOLD:
stripe_circuit_breaker.open()
# Route all traffic to backup provider
Retry logic:
Первая попытка: Stripe
Если timeout → Вторая попытка: Stripe (exponential backoff)
Если всё ещё timeout → Третья попытка: PayPal
Максимум 3 попытки, максимум 30 секунд
Фаза 5: Security
PCI-DSS Compliance (Level 1)
- Никогда не храним credit card data — используем токены
- Вся коммуникация через HTTPS с TLS 1.2+
- Database encryption at rest (AES-256)
- Audit logging всех операций
- IP whitelisting для провайдеров
- Rate limiting (10 платежей в минуту per customer)
- Fraud detection (странная сумма, странная геолокация)
Пример fraud detection:
if (new_amount > customer.avg_payment * 10 and
customer.last_location != current_location and
time_since_last_payment < 5_minutes):
flag_for_review = True
send_verification_email(customer)
Фаза 6: Мониторинг и метрики
Ключевые метрики:
1. Success rate per provider
- Stripe: 99.5%
- PayPal: 99.2%
2. Latency percentiles
- p50: 200ms
- p95: 450ms
- p99: 800ms
3. Error rates by code
- declined_card: 2.5%
- insufficient_funds: 0.8%
- timeout: 0.1%
4. Revenue metrics
- Total processed: $XXX
- Failed payments: $YYY
- Failed rate by geography
Мониторинг:
- Prometheus для метрик
- ELK для логов
- PagerDuty для алертов
- Grafana для dashboards
Алерты:
- Success rate < 95% → page on-call
- P99 latency > 2 sec → warning
- Circuit breaker trips → page on-call
Фаза 7: Развёртывание
Стратегия:
-
Stage 1: Canary (1% трафика, real transactions, 2 недели)
- Validate implementation
- Monitor fraud rate
- Adjust settings
-
Stage 2: Gradual rollout (10% → 50% → 100%, 3 недели)
- Run А/В тест (старая vs новая система)
- Monitor success rate
- Have instant rollback plan
-
Stage 3: Full migration
- Sunset старой платёжной системы
- Archive старые данные
Результаты
После запуска:
- ✅ Success rate: 99.3%
- ✅ Latency p95: 380ms
- ✅ Uptime: 99.98%
- ✅ Zero PCI violations за 2 года
- ✅ Обработано $500M+ через сервис
- ✅ Team scales from 2 engineers to 6 (нужны ещё люди)
Ключевые уроки
- Start with non-functional requirements, not features
- Resilience first — платёжные системы не могут быть down
- Compliance drives architecture — PCI-DSS constraints are real
- Fallback is not optional — single provider is a single point of failure
- Monitoring is critical — you need to know in real-time if payments fail
- Test in production carefully — use canary deployments and feature flags
Этот опыт показал мне важность системного мышления и взаимодействия с разными stakeholders при проектировании критичных сервисов.