+ Most practical on idempotency, recovery, and security.
- Read-ID validation and badge updates have consistency gaps.
--- name: backend-architect description: "Use this agent when designing APIs, building server-side logic, implementing databases, or architecting scal
| Category | Development › Data & databases |
|---|---|
| Tags | DraftingAnalyzingDeveloperCode |
--- name: backend-architect description: "Use this agent when designing APIs, building server-side logic, implementing databases, or architecting scalable backend systems. This agent specializes in creating robust, secure, and performant backend services. Examples:\n\n<example>\nContext: Designing a new API\nuser: \"We need an API for our social sharing feature\"\nassistant: \"I'll design a RESTful API with proper authentication and rate limiting. Let me use the backend-architect agent to create a scalable backend architecture.\"\n<commentary>\nAPI design requires careful consideration of security, scalability, and maintainability.\n</commentary>\n</example>\n\n<example>\nContext: Database design and optimization\nuser: \"Our queries are getting slow as we scale\"\nassistant: \"Database performance is critical at scale. I'll use the backend-architect agent to optimize queries and implement proper indexing strategies.\"\n<commentary>\nDatabase optimization requires deep understanding of query patterns and indexing strategies.\n</commentary>\n</example>\n\n<example>\nContext: Implementing authentication system\nuser: \"Add OAuth2 login with Google and GitHub\"\nassistant: \"I'll implement secure OAuth2 authentication. Let me use the backend-architect agent to ensure proper token handling and security measures.\"\n<commentary>\nAuthentication systems require careful security considerations and proper implementation.\n</commentary>\n</example>" model: opus color: purple tools: Write, Read, Edit, Bash, Grep, Glob, WebSearch, WebFetch permissionMode: default --- You are a master backend architect with deep expertise in designing scalable, secure, and maintainable server-side systems. Your experience spans microservices, monoliths, serverless architectures, and everything in between. You excel at making architectural decisions that balance immediate needs with long-term scalability. Your primary responsibilities: 1. **API Design & Implementation**: When building APIs, you will: - Design RESTful APIs following OpenAPI specifications - Implement GraphQL schemas when appropriate - Create proper versioning strategies - Implement comprehensive error handling - Design consistent response formats - Build proper authentication and authorization 2. **Database Architecture**: You will design data layers by: - Choosing appropriate databases (SQL vs NoSQL) - Designing normalized schemas with proper relationships - Implementing efficient indexing strategies - Creating data migration strategies - Handling concurrent access patterns - Implementing caching layers (Redis, Memcached) 3. **System Architecture**: You will build scalable systems by: - Designing microservices with clear boundaries - Implementing message queues for async processing - Creating event-driven architectures - Building fault-tolerant systems - Implementing circuit breakers and retries - Designing for horizontal scaling 4. **Security Implementation**: You will ensure security by: - Implementing proper authentication (JWT, OAuth2) - Creating role-based access control (RBAC) - Validating and sanitizing all inputs - Implementing rate limiting and DDoS protection - Encrypting sensitive data at rest and in transit - Following OWASP security guidelines 5. **Performance Optimization**: You will optimize systems by: - Implementing efficient caching strategies - Optimizing database queries and connections - Using connection pooling effectively - Implementing lazy loading where appropriate - Monitoring and optimizing memory usage - Creating performance benchmarks 6. **DevOps Integration**: You will ensure deployability by: - Creating Dockerized applications - Implementing health checks and monitoring - Setting up proper logging and tracing - Creating CI/CD-friendly architectures - Implementing feature flags for safe deployments - Designing for zero-downtime deployments **Technology Stack Expertise**: - Languages: Node.js, Python, Go, Java, Rust - Frameworks: Express, FastAPI, Gin, Spring Boot - Databases: PostgreSQL, MongoDB, Redis, DynamoDB - Message Queues: RabbitMQ, Kafka, SQS - Cloud: AWS, GCP, Azure, Vercel, Supabase **Architectural Patterns**: - Microservices with API Gateway - Event Sourcing and CQRS - Serverless with Lambda/Functions - Domain-Driven Design (DDD) - Hexagonal Architecture - Service Mesh with Istio **API Best Practices**: - Consistent naming conventions - Proper HTTP status codes - Pagination for large datasets - Filtering and sorting capabilities - API versioning strategies - Comprehensive documentation **Database Patterns**: - Read replicas for scaling - Sharding for large datasets - Event sourcing for audit trails - Optimistic locking for concurrency - Database connection pooling - Query optimization techniques Your goal is to create backend systems that can handle millions of users while remaining maintainable and cost-effective. You understand that in rapid development cycles, the backend must be both quickly deployable and robust enough to handle production traffic. You make pragmatic decisions that balance perfect architecture with shipping deadlines.
This agent setup is for shaping backend architecture and designing APIs or data layers. It addresses REST, GraphQL, versioning, authentication and authorization, SQL/NoSQL choices, and indexing.
Claude is the most complete and production-ready. ChatGPT is reliability-focused but misses a core API, while Gemini is weakened by Redis-related inaccuracies.
+ Most practical on idempotency, recovery, and security.
- Read-ID validation and badge updates have consistency gaps.
+ Strong event-loss protection through the outbox pattern.
- It omits room creation and duplicate-room constraints.
+ Clearly explains read cursors and realtime delivery.
- Its lossless Pub/Sub claim and eviction policy are unsafe.
| Criterion | ChatGPT | Claude | Gemini | Leader |
|---|---|---|---|---|
| Instruction following | 9 | 10 | 9 | Claude +11% |
| Accuracy | 8 | 8 | 7 | Tie |
| Specificity | 9 | 10 | 9 | Claude +11% |
| Structure | 9 | 9 | 9 | Tie |
| Right length | 8 | 7 | 8 | Tie |
Scored 1–10 by gpt-5.6-sol with model names hidden (2026-09-24). This is an AI review, not a measurement.
We gave three models the same input and copied their answers unedited. Each ran in its CLI (an agent harness), and answers in the ChatGPT or Claude apps or on the web may differ. Outputs are in Korean.
[Pasted material] 저희는 중고거래 플랫폼을 운영 중인 스타트업입니다 (Node.js + Express + PostgreSQL, 가입자 12만 명). 1:1 채팅과 실시간 알림 기능을 새로 만들어야 하는데, 동시 접속 1만 명을 버틸 수 있는 API와 DB 스키마, 메시지 읽음 처리 로직을 설계해 주세요.
Client
├─ REST API ──> Express API 서버 ──> PostgreSQL
└─ WebSocket ─> Realtime Gateway ──> Redis Pub/Sub
└─ PostgreSQL
ws 또는 Socket.IO 사용. 단순성과 성능을 중시하면 ws 권장동시 접속 1만 명은 단일 Node.js 서버에서도 처리 가능할 수 있지만, 장애와 배포를 고려해 다음처럼 시작하는 것이 안전합니다.
WebSocket 연결 수가 많아도 PostgreSQL 연결 수를 같이 늘리면 안 됩니다. 실시간 연결 수와 DB 연결 수는 별도로 관리해야 합니다.
기존 사용자 테이블을 사용한다고 가정합니다.
CREATE TABLE chat_rooms (
id BIGSERIAL PRIMARY KEY,
item_id BIGINT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
last_message_id BIGINT NULL
);
CREATE TABLE chat_room_members (
room_id BIGINT NOT NULL REFERENCES chat_rooms(id),
user_id BIGINT NOT NULL REFERENCES users(id),
joined_at TIMESTAMPTZ NOT NULL DEFAULT now(),
left_at TIMESTAMPTZ NULL,
PRIMARY KEY (room_id, user_id)
);
1:1 채팅이라도 chat_room_members를 사용하면 차후 다자간 채팅으로 확장하기 쉽습니다.
CREATE TABLE chat_messages (
id BIGSERIAL PRIMARY KEY,
room_id BIGINT NOT NULL REFERENCES chat_rooms(id),
sender_id BIGINT NOT NULL REFERENCES users(id),
client_message_id UUID NOT NULL,
body TEXT NOT NULL,
message_type VARCHAR(20) NOT NULL DEFAULT 'text',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
deleted_at TIMESTAMPTZ NULL,
UNIQUE (sender_id, client_message_id)
);
CREATE INDEX idx_chat_messages_room_id_id
ON chat_messages (room_id, id DESC);
CREATE INDEX idx_chat_messages_room_id_created_at
ON chat_messages (room_id, created_at DESC);
client_message_id는 클라이언트가 생성하는 UUID입니다. 네트워크 재전송 시 같은 메시지가 중복 생성되지 않도록 하는 멱등성 키입니다.
CREATE TABLE chat_room_reads (
room_id BIGINT NOT NULL REFERENCES chat_rooms(id),
user_id BIGINT NOT NULL REFERENCES users(id),
last_read_message_id BIGINT NULL REFERENCES chat_messages(id),
last_read_at TIMESTAMPTZ NULL,
PRIMARY KEY (room_id, user_id)
);
1:1 채팅에서는 메시지마다 읽음 행을 만들지 않고, 사용자가 마지막으로 읽은 메시지 ID만 저장합니다.
CREATE TABLE notifications (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id),
type VARCHAR(50) NOT NULL,
payload JSONB NOT NULL,
dedupe_key VARCHAR(200) NULL,
read_at TIMESTAMPTZ NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
UNIQUE (user_id, dedupe_key)
);
CREATE INDEX idx_notifications_user_created
ON notifications (user_id, created_at DESC);
CREATE INDEX idx_notifications_unread
ON notifications (user_id, created_at DESC)
WHERE read_at IS NULL;
알림 payload에는 최소한 다음 정보를 포함합니다.
{
"roomId": 123,
"messageId": 456,
"senderId": 789,
"preview": "안녕하세요"
}
1. 클라이언트가 WebSocket 또는 REST로 메시지 전송
2. 서버가 room 멤버십과 차단 여부 확인
3. PostgreSQL transaction 시작
4. chat_messages INSERT
5. chat_rooms.last_message_id, updated_at 갱신
6. 상대방 알림 INSERT
7. transaction commit
8. Redis Pub/Sub으로 message.created 발행
9. 각 Gateway가 연결된 사용자에게 WebSocket 전달
메시지 저장이 성공한 뒤에만 실시간 이벤트를 발행해야 합니다. 데이터 저장 전에 이벤트를 보내면 클라이언트가 존재하지 않는 메시지를 보게 될 수 있습니다.
다만 PostgreSQL commit 직후 프로세스가 죽으면 Redis 발행이 누락될 수 있으므로, 운영 환경에서는 Outbox 패턴을 권장합니다.
CREATE TABLE event_outbox (
id BIGSERIAL PRIMARY KEY,
event_type VARCHAR(100) NOT NULL,
aggregate_id BIGINT NOT NULL,
payload JSONB NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
published_at TIMESTAMPTZ NULL
);
CREATE INDEX idx_event_outbox_unpublished
ON event_outbox (id)
WHERE published_at IS NULL;
메시지와 Outbox 이벤트를 같은 transaction에서 저장하고, 별도 worker가 Redis에 발행합니다.
GET /v1/chat/rooms?cursor=123&limit=30
응답:
{
"data": [
{
"roomId": 123,
"itemId": 88,
"counterpart": {
"userId": 42,
"nickname": "user42"
},
"lastMessage": {
"id": 456,
"body": "네, 확인했습니다.",
"createdAt": "2026-09-24T10:00:00Z"
},
"unreadCount": 3,
"updatedAt": "2026-09-24T10:00:00Z"
}
],
"nextCursor": "456"
}
페이지네이션은 OFFSET 대신 cursor 기반으로 처리합니다.
GET /v1/chat/rooms/{roomId}/messages?before=456&limit=50
SELECT *
FROM chat_messages
WHERE room_id = $1
AND id < $2
AND deleted_at IS NULL
ORDER BY id DESC
LIMIT 50;
메시지 ID가 전역적으로 증가하므로 cursor로 사용하기 좋습니다. 서버에서는 반환 순서를 클라이언트 요구에 맞게 뒤집을 수 있습니다.
REST fallback과 재시도 지원을 위해 다음 API를 둡니다.
POST /v1/chat/rooms/{roomId}/messages
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
{
"body": "안녕하세요",
"messageType": "text",
"clientMessageId": "550e8400-e29b-41d4-a716-446655440000"
}
응답:
{
"messageId": 456,
"roomId": 123,
"senderId": 10,
"body": "안녕하세요",
"createdAt": "2026-09-24T10:00:00Z"
}
PUT /v1/chat/rooms/{roomId}/read
{
"lastReadMessageId": 456
}
GET /v1/notifications?cursor=123&limit=30
PUT /v1/notifications/{notificationId}/read
PUT /v1/notifications/read-all
핵심은 클라이언트가 “현재 보고 있는 마지막 메시지 ID”를 서버에 보내는 것입니다.
INSERT INTO chat_room_reads (
room_id,
user_id,
last_read_message_id,
last_read_at
)
VALUES ($1, $2, $3, now())
ON CONFLICT (room_id, user_id)
DO UPDATE SET
last_read_message_id = GREATEST(
chat_room_reads.last_read_message_id,
EXCLUDED.last_read_message_id
),
last_read_at = CASE
WHEN EXCLUDED.last_read_message_id >
chat_room_reads.last_read_message_id
THEN now()
ELSE chat_room_reads.last_read_at
END;
항상 GREATEST를 사용해야 합니다. 네트워크 지연으로 이전 메시지의 읽음 요청이 늦게 도착해도 읽음 위치가 뒤로 가지 않게 합니다.
읽지 않은 메시지 수:
SELECT COUNT(*)
FROM chat_messages m
LEFT JOIN chat_room_reads r
ON r.room_id = m.room_id
AND r.user_id = $2
WHERE m.room_id = $1
AND m.sender_id <> $2
AND m.deleted_at IS NULL
AND (
r.last_read_message_id IS NULL
OR m.id > r.last_read_message_id
);
대화방 목록에서 모든 방의 unread count를 매번 COUNT하면 비용이 커질 수 있습니다. 초기에는 위 방식으로 시작하되, 트래픽 증가 시 다음 중 하나를 적용합니다.
chat_room_members.unread_count를 비정규화하여 관리(room_id, user_id, last_read_message_id) 기준으로 계산하고 방 목록을 제한읽음 이벤트는 WebSocket으로 상대방에게 전달할 수 있습니다.
{
"type": "chat.read",
"roomId": 123,
"userId": 42,
"lastReadMessageId": 456
}
연결 시:
wss://api.example.com/realtime
Authorization: Bearer <access-token>
서버는 인증된 사용자 ID를 기준으로 Redis에 연결 정보를 관리합니다.
주요 이벤트:
{
"type": "chat.message.created",
"data": {
"roomId": 123,
"messageId": 456,
"senderId": 10,
"body": "안녕하세요",
"createdAt": "2026-09-24T10:00:00Z"
}
}
{
"type": "notification.created",
"data": {
"notificationId": 99,
"type": "new_chat_message",
"roomId": 123
}
}
{
"type": "chat.read",
"data": {
"roomId": 123,
"userId": 42,
"lastReadMessageId": 456
}
}
연결 안정성을 위해 다음을 포함합니다.
eventId 또는 메시지 ID 기반 중복 제거lastEventId 전달messageId 정렬WebSocket을 신뢰성 있는 저장소로 사용하지 말고, 재연결 후 REST API로 누락 메시지를 보완하는 구조가 안전합니다.
간단한 초기 구조:
chat:room:{roomId}
user:{userId}:notifications
Redis Pub/Sub은 전달 보장이 없으므로, 중요한 이벤트 자체를 Redis에만 보관하면 안 됩니다. 메시지 원본은 PostgreSQL에 있고 Redis는 실시간 전달용으로만 사용해야 합니다.
전달 유실 복구가 중요하면 Redis Streams 또는 Outbox worker를 사용합니다.
stream:realtime-events
consumer-group: realtime-gateway
다만 WebSocket 서버가 직접 모든 이벤트를 소비하는 방식은 사용자 라우팅 구조가 복잡해질 수 있으므로, 초기에는 Outbox worker + Redis Pub/Sub로 시작하고 장애 복구 요구가 커질 때 Streams로 확장하는 방식이 현실적입니다.
dedupe_key 사용예시 rate limit:
메시지 전송: 사용자당 10초에 30회
WebSocket 연결: IP당 분당 20회
대화방 목록: 사용자당 초당 10회
Load Balancer
├─ Express API × 3
├─ Realtime Gateway × 3
├─ Outbox Worker × 2
├─ PostgreSQL Primary
├─ PostgreSQL Read Replica
└─ Redis
읽기 트래픽은 replica로 분산할 수 있지만, 메시지 생성 직후 이력 조회나 읽음 처리 직후 상태 조회처럼 read-after-write가 필요한 요청은 잠시 primary를 사용하거나 애플리케이션에서 일관성을 보장해야 합니다.
가장 먼저 구현할 범위는 다음입니다.
last_read_message_id 방식의 읽음 처리이 구조면 현재 12만 가입자 규모에서 시작하면서도, 동시 접속 1만 명과 이후 수평 확장에 대응할 수 있습니다.
| Advanced Text Converter for Large Datasets | |
| AI-powered data extraction and organization tool | |
| AI2sql SQL Model — Query Generator | |
| base-R | |
| Building a Scalable Search Service with FastAPI and PostgreSQL |