Goal

Get a fast overview of full-stack architecture, with a focus on backend systems.

  1. A high-level architecture and technology stack map for full-stack projects.
  2. A flash-sale e-commerce case study to connect the architecture with key backend technologies.
  3. Practical references for project technology selection and architecture design.

Full-Stack Architecture Overview

The main request path can be understood as “frontend + backend”. The frontend handles client-side business logic, client frameworks, and local runtime behavior. The backend handles ingress, application logic, data, asynchronous workflows, and runtime infrastructure.

AreaLevelMain LayerProblem SolvedCommon Technologies / Patterns / Infrastructure
Frontend1Frontend application layerClient-side business logic, page flows, user interactions, business stateWeb App, Mobile App, Mini Program, Dashboard, Content Site
Frontend2Framework layerClient development model, components, routing, state, API callsAndroid, iOS, React, Vue, Rax, Next.js, Pinia, TanStack Query
Frontend3Runtime and rendering layerCode compilation, runtime, virtual machine, rendering, threads, event loopCompiler, JS VM, JVM, ART, WebView, Browser Rendering, Native Rendering
Backend4Ingress layerRequest entry, routing, reverse proxy, traffic controlNginx, API Gateway, web frameworks: Gin, Gorilla Mux, Spring MVC
Backend5AuthN / AuthZ layerIdentity, sessions, roles, permissions, resource access controlJWT, Session, OAuth2, OIDC, RBAC, auth frameworks/libraries: Better Auth
Backend6Application layerUse-case orchestration, transaction boundaries, external dependency calls, error semanticsService, Use Case, Application Service, business state machine
Backend7Domain model layerBusiness concepts, business rules, state transitions, domain eventsEntity, Value Object, Aggregate, Domain Event
Backend8Data and storage layerPersistence, queries, caching, search, uploads, downloadsMySQL, PostgreSQL, Redis, Elasticsearch, S3, MinIO
Backend9Async and real-time layerTraffic spike buffering, long-running jobs, retries, long-running workflows, real-time progress updatesKafka, RabbitMQ, River, workflow engines: Temporal, Hatchet, SSE, WebSocket
Backend10Framework and runtime foundationBackend frameworks, language runtimes, build tools, deployment runtimeFrameworks: Spring Boot, Gin, NestJS, Express, Fastify
Runtimes: JVM, Go runtime, Node.js runtime
Build/package management: Maven, Gradle, Go toolchain, npm, pnpm
Deployment infrastructure: Docker, Kubernetes, cloud runtime

Cross-cutting capabilities span all layers and support security, stability, and maintainability.

Cross-Cutting CapabilityLayers CoveredProblem SolvedCommon Technologies / Cloud Capabilities
Configuration and environmentsAllMulti-environment configuration, secrets, feature flags, runtime parameters.env, Viper, Vault, Secret Manager, ConfigMap, Feature Flag
Security governanceAllAttack prevention, data leakage prevention, privilege control, abuse prevention, audit and complianceWAF, CORS, Rate Limit, KMS, IAM, Gitleaks, Trivy, bcrypt
ObservabilityAllLogs, metrics, distributed tracing, health checks, alerts, capacity planningPrometheus, Grafana, Loki, ELK, OpenTelemetry, CloudWatch
Cloud-managed capabilitiesAllUse managed services instead of self-managed infrastructure to reduce operations costCDN, LB, RDS, Redis, S3/OSS/COS, SQS, EKS, Cloud Run
Release and change managementApplication layer, data and storage layer, async and real-time layer, framework and runtime foundationProgressive delivery, fast rollback, database changes, configuration changesCI/CD, Blue-Green, Canary, Schema Migration, Rollback
AI governanceApplication layer, data and storage layer, async and real-time layer, framework and runtime foundationPrompt injection protection, content safety, model evaluation, cost control, call auditGuardrails, Moderation, Eval, Token Budget, Prompt Audit, Model Router

AI Application Backend Supplement

An AI application backend usually adds model calls, context retrieval, tool calls, asynchronous jobs, and governance capabilities on top of a traditional backend path.

AI Backend CapabilityRelated PathCommon Technologies / Patterns
Retrieval augmentationData and storage layer, application layerRAG, Embedding Store, pgvector, Milvus, Pinecone, Weaviate
Task orchestrationApplication layer, async and real-time layerAI Use Case, Agent Workflow, Prompt Orchestration, Tool Calling, Agent Task Queue
Model servingFramework and runtime foundationOllama, vLLM, Triton, SageMaker, Vertex AI
Streaming responsesAsync and real-time layer, ingress layerStreaming Response, SSE, WebSocket
Governance and evaluationCross-cutting capabilityGuardrails, Moderation, Eval, Token Budget, Prompt Audit, Model Router

Connecting the Stack with a Flash-Sale E-Commerce System

What Is the Business Scenario?

100 phones available for limited-time purchase
A large number of users submit requests at the same time
The system must guarantee performance, data consistency, and security

Why Use This Scenario?

A flash-sale system is a useful backend architecture case because it includes both a complete business flow and system quality requirements. On the business side, it needs login, eligibility checks, stock decrement, order creation, payment, and cancellation. On the system side, it needs concurrency control, oversell prevention, idempotency, traffic spike buffering, compensation, scaling, and troubleshooting.

To use this scenario to connect the backend technology stack, first break down the problems, then map each problem type to the backend capability layer that solves it:

Business problem -> functional requirement -> application layer / domain layer / data layer
System problem -> non-functional requirement -> ingress layer / cache / MQ / observability / deployment runtime

Requirements and Capability Needs in This Scenario

The requirements in this scenario can be divided into two categories: functional requirements complete the business flow, while non-functional requirements keep the system stable and correct under high traffic, failures, and business edge cases.

Functional requirements:

Functional RequirementBackend CapabilityTypical Technologies / Methods
Users must be logged in and eligible to participateAuthentication and authorization layer, risk controlSession / JWT, RBAC, eligibility token, CAPTCHA, IP/user rate limiting
The campaign must start and end at specific timesBusiness rules, campaign configurationCampaign configuration, time-window checks, feature switches
Stock must support reads and atomic decrementsData and storage layer, consistency controlRedis stock, DB stock, stock ledger
Each user can only purchase onceIdempotency and deduplicationUser-level dedup key, request_id, unique order index
A successful purchase must create an orderApplication layer, data persistenceApplication Service, Order Worker, MySQL
Orders need payment, cancellation, and closureDomain model layer, state transitionsOrder state machine, domain events, payment callback
Stock must be released after payment timeoutAsync jobs, compensationDelayed queue, scheduled job, stock rollback

Non-functional requirements can be grouped into four categories: high performance, high availability, high scalability, and data consistency.

CategoryNon-Functional RequirementBackend CapabilityTypical Technologies / Methods
High performanceMany users enter the campaign page at the same timeIngress layer, traffic control, static asset accelerationCDN, Nginx, API Gateway, Rate Limit
High performanceTraffic spikes must not directly overload the databaseCache, traffic buffering, async processingRedis, MQ, Worker, queuing
High performanceHot products must not overload the systemHotspot cache, hotspot isolation, rate limitingLocal cache, Redis, Rate Limit, stock sharding
High availabilityOrders must not be lost when some components failReliable messaging, retry, compensationLocal message table, transactional messages, Retry, DLQ, reconciliation scan
High availabilityIssues must be diagnosableObservabilitytrace ID, Metrics, Logs, Tracing, alerts
High scalabilityThe system must scale as traffic growsHorizontal scaling, capacity planningStateless services, multiple replicas, Redis Cluster, MQ Cluster, Worker scaling
Data consistency100 phones must not be oversoldAtomic decrement, transactional fallbackRedis Lua, DB optimistic locking
Data consistencyDuplicate requests must not create duplicate ordersIdempotency, deduplication, unique constraintsrequest_id, idempotency table, unique order index
Data consistencyPayment timeout must not hold stock foreverState transitions, compensationDelayed queue, order closure, stock release

When functional and non-functional requirements are connected, they form the main flash-sale system path:

Preparation phase
-> Preload product stock into Redis
-> Generate campaign configuration, purchase limits, and eligibility tokens

Request phase
-> CDN / Nginx / Gateway
-> Rate limiting, risk control, login check
-> Check campaign time, eligibility, one-order-per-user rule
-> Atomically decrement stock with Redis Lua
-> Publish to MQ after success

Async order phase
-> Worker creates order asynchronously
-> Persist order into MySQL
-> Cancel order after payment timeout
-> Compensate stock

Flash-Sale System Evolution Path

Stage One: Monolith

User -> Nginx -> Spring Boot / Gin monolith -> MySQL
ItemContent
GoalUnderstand basic web architecture, complete the business flow, and learn Controller / Service / DAO
SolvesBasic ordering, product query, user login, order persistence
Does not solveHigh database pressure under concurrency, possible overselling, limited single-instance scalability
Suitable forSmall projects, internal systems, MVPs

Core path code:

func Seckill(ctx context.Context, userID, skuID int64) {
	// Start a transaction so stock decrement and order creation succeed or fail together.
	tx := db.Begin()

	// Lock the stock row to avoid concurrent requests reading the same stock value.
	stock := tx.Query("select stock from sku where id = ? for update", skuID)
	if stock <= 0 {
		tx.Rollback()
		return
	}

	// Deduct stock.
	tx.Exec("update sku set stock = stock - 1 where id = ?", skuID)

	// Create order.
	tx.Exec("insert into orders(user_id, sku_id, status) values (?, ?, 'created')", userID, skuID)
	tx.Commit()
}

Related technology stack:

CategoryRoleJS / NodeGoJava
Web frameworkReceive requests, route requests, organize APIsExpress, NestJS, FastifyGin, Echo, FiberSpring Boot, Spring MVC
Data accessQueries, transactions, CRUDPrisma, TypeORM, Drizzledatabase/sql, GORM, sqlc, entMyBatis, Spring Data JPA, MyBatis-Plus
Basic engineeringConfiguration, logging, validation, project organizationdotenv, Pino, ZodViper, zap, validatorSpring Config, Logback, Hibernate Validator

This stage completes the loop of reading stock, decrementing stock, and creating orders. As concurrency increases, requests hit the database directly, and stock row locks plus order writes become bottlenecks.

Stage Two: Introduce Redis

User
  |
Nginx
  |
App
  |-- Redis: hot products, stock, eligibility, deduplication
  |-- MySQL: orders, users, product persistence
ItemContent
GoalReduce database pressure, improve hot-read performance, and use atomic operations to control stock decrement
SolvesHot product reads, fast stock decrement, initial duplicate-order prevention
Does not solveAsync traffic buffering, order persistence pressure, Redis/DB consistency, hot keys
Upgrade signalRedis can handle reads/writes, but order creation, payment, notifications, or later steps begin to block

Core path code:

func Seckill(ctx context.Context, userID int64, skuID string) {
	stockKey := "stock:" + skuID
	userKey := fmt.Sprintf("seckill:user:%d:sku:%s", userID, skuID)

	// Redis Lua atomically completes stock decrement and user deduplication.
	result := redis.Eval(decrStockLua, stockKey, userKey)
	if result != "ok" {
		return
	}

	// Create the order synchronously after the stock pre-decrement succeeds.
	db.Exec("insert into orders(user_id, sku_id, status) values (?, ?, 'created')", userID, skuID)
}

Related technology stack:

CategoryRoleJS / NodeGoJava
Redis clientAccess Redis and execute Luaioredis, node-redisgo-redisSpring Data Redis, Lettuce, Jedis
Cache and stock decrementHot cache, stock pre-decrement, deduplicationRedis Lua, lru-cacheRedis Lua, RistrettoRedis Lua, Caffeine, Redisson
Rate limiting and anti-abuseControl user, IP, and API frequencyBottleneck, rate-limiter-flexiblex/time/rate, redis-rateBucket4j, Resilience4j

This stage moves hot stock decrement from the database to Redis, improving stock checks and decrement throughput. Orders are still written synchronously to the database, so database writes still block when request peaks continue to grow.

Stage Three: Introduce a Message Queue

User
  |
Gateway / Nginx
  |
App
  |
Redis Lua stock decrement
  |
MQ
  |
Order Worker
  |
MySQL
ItemContent
GoalSmooth traffic spikes, return quickly from requests, and create orders asynchronously in the background
SolvesInstant traffic spikes, synchronous order-write pressure, blocking from long-running tasks
Does not solveDuplicate messages, message loss, MQ backlog, stock decremented but order creation failed
Upgrade signalMore modules appear, and order, stock, user, and payment services need independent evolution and scaling

Core path code:

func Seckill(ctx context.Context, userID int64, skuID, requestID string) {
	userKey := fmt.Sprintf("seckill:user:%d:sku:%s", userID, skuID)

	// In the request phase, only validate eligibility, deduplicate, and pre-decrement stock.
	result := redis.Eval(decrStockLua, "stock:"+skuID, userKey)
	if result != "ok" {
		return
	}

	// Publish a message after stock decrement succeeds, then return quickly.
	mq.Publish("order.create", OrderCreateMessage{UserID: userID, SkuID: skuID, RequestID: requestID})
}

func ConsumeOrderCreate(msg OrderCreateMessage) {
	// Create the order asynchronously. A unique request_id constraint guarantees idempotency.
	db.Exec(`
		insert into orders(user_id, sku_id, request_id, status)
		values (?, ?, ?, 'created')
		on duplicate key update request_id = request_id
	`, msg.UserID, msg.SkuID, msg.RequestID)
}

Related technology stack:

CategoryRoleJS / NodeGoJava
Message queueTraffic buffering, async order creation, service decouplingKafkaJS, amqplib, BullMQkafka-go, amqp091-go, Asynq, RiverSpring Kafka, Spring AMQP, RocketMQ Client
Consumer reliabilityIdempotency, retry, dead-letter handling, duplicate consumption controlIdempotency Key, Retry, DLQIdempotency Key, Retry, DLQIdempotency Key, Retry, DLQ
Delayed tasksPayment timeout, order closure, stock compensationBullMQ, AgendaAsynq, RiverQuartz, Spring Batch, RocketMQ Delay Message

This stage uses MQ to buffer traffic spikes. The request path returns quickly, and orders are created asynchronously by workers. Message redelivery, worker restarts, and consumption failures will happen, so order creation must be idempotent.

Production systems must also handle the failure point where stock has been decremented but the message publish fails. A common pattern is to write the pending event to a local message table / Outbox first, let a background job publish it to MQ, and use reconciliation scans to catch events that were not published successfully. Consumers should use message_id, request_id, or a unique order constraint to guarantee idempotency and avoid duplicate orders from duplicate messages.

Stage Four: Service Decomposition

User
  |
API Gateway
  |-- User Service -> User DB
  |-- Order Service -> Order DB
  |-- Stock Service -> Redis / Stock DB

Order Service -> MQ -> Order Worker
Order Worker -> Stock Service / Payment Service
ItemContent
GoalSupport team collaboration, independent service deployment, and independent service scaling
SolvesCoupling among user/order/stock modules, service-specific scaling, unclear ownership boundaries
Does not solveDistributed transaction complexity, harder trace debugging, higher service governance cost
ConstraintFor high concurrency, prioritize cache, traffic buffering, rate limiting, and idempotency. Service decomposition is suitable after business complexity, team size, and independent deployment needs grow.

Core path code:

func CreateSeckillOrder(ctx context.Context, userID int64, skuID, requestID string) {
	// The order service first calls the stock service to reserve stock.
	reservationID := stockService.Reserve(userID, skuID, requestID)

	// Create a pending order after stock reservation succeeds.
	orderID := orderRepo.CreatePending(userID, skuID, reservationID)

	// Publish an order event to drive payment, notification, and stock confirmation.
	mq.Publish("order.created", OrderCreatedEvent{OrderID: orderID, ReservationID: reservationID})
}

func ReserveStock(userID int64, skuID, requestID string) string {
	// The stock service still uses Redis Lua internally to make decrement and reservation atomic.
	return redis.Eval(reserveStockLua, "stock:"+skuID, "reservation:"+requestID)
}

func OnOrderCreateFailed(reservationID string) {
	// Release reserved stock when order creation fails, preventing stock from being held forever.
	stockService.Release(reservationID)
}

Related technology stack:

CategoryRoleJS / NodeGoJava
Service communicationInter-service RPC / HTTP callsgRPC-js, tRPC, OpenAPIgRPC-Go, Connect-Go, RestygRPC Java, OpenFeign, Dubbo
Microservice frameworkService governance, module organization, team collaborationNestJS Microservices, Moleculergo-zero, Kratos, KitexSpring Cloud, Dubbo
Service governanceService discovery, configuration, rate limiting, circuit breakingConsul, etcdConsul, etcdNacos, Eureka, Sentinel, Resilience4j
Distributed consistencySaga, compensation, long-running workflow stateTemporal TypeScript SDKTemporal Go SDKSeata, Temporal Java SDK

This stage splits users, orders, and stock into independent services that can scale separately according to load. Cross-service paths require compensation events; otherwise order success, stock failure, and payment failure can lead to inconsistent states.

After service decomposition, order, stock, and payment usually cannot rely on a single database transaction. The cross-service flow should be managed by a Saga state machine, for example INIT -> STOCK_RESERVED -> ORDER_CREATED -> PAID -> DONE. When any step fails, the flow enters a compensation state to release stock, close the order, or cancel payment. Compensation can also fail, so it needs retries, idempotency, and an operator intervention path.

Stage Five: Highly Available Production Version

User
  |
CDN / WAF / LB
  |
API Gateway cluster
  |
Service replicas
  |-- Redis Cluster
  |-- MQ Cluster
  |-- MySQL primary-replica / sharding
  |-- Object Storage

Observability
  |-- Metrics: Prometheus
  |-- Dashboard: Grafana
  |-- Logs: ELK / Loki
  |-- Tracing: Jaeger / Tempo / SkyWalking
ItemContent
GoalSupport high concurrency, failure recovery, capacity scaling, and production troubleshooting
SolvesSingle points of failure, insufficient capacity, lack of production visibility, weak recovery
Does not solveArchitecture complexity, operations cost, distributed consistency difficulty
Suitable forSystems with large user volume, core transaction paths, and high availability/disaster recovery requirements

Core path code:

func SeckillHandler(ctx context.Context, req SeckillRequest) {
	// Rate limit at the gateway or service ingress to protect the backend core path.
	if !limiter.Allow(req.UserID, req.IP) {
		return
	}

	// Create a trace for one flash-sale request across gateway, services, MQ, and database.
	trace := tracing.Start("seckill", req.RequestID)

	// Execute the core business path.
	result := seckillService.Submit(ctx, req.UserID, req.SkuID, req.RequestID)

	// Record metrics and logs for capacity analysis, troubleshooting, and alerts.
	metrics.Record("seckill", result)
	logs.Write(req.RequestID, req.UserID, req.SkuID, result)
	trace.End()
}

Related technology stack:

CategoryRoleJS / NodeGoJava
ObservabilityMetrics, logs, tracing, alertsOpenTelemetry JS, prom-client, PinoOpenTelemetry Go, Prometheus Client, zapMicrometer, Actuator, OpenTelemetry Java Agent
Performance diagnosisCPU, memory, blocking, slow-call analysisclinic.js, 0xpprofJFR, Arthas
Deployment and orchestrationContainerization, replicas, rolling releases, scalingDocker, Kubernetes, HelmDocker, Kubernetes, HelmDocker, Kubernetes, Helm
High-availability infrastructureGateway, load balancing, cache cluster, database clusterNginx, Envoy, Redis Cluster, MQ ClusterNginx, Envoy, Redis Cluster, MQ ClusterNginx, Envoy, Redis Cluster, MQ Cluster

This stage improves availability through replicas, clusters, rate limiting, and observability. As more components are added, troubleshooting depends on a consistent trace ID, metrics, logs, and alerts.

How to Select Technologies and Design Architecture for Real Business

Architecture design should first clarify business requirements, then translate them into technical requirements, and finally choose between self-managed infrastructure and managed cloud services.

Decision sequence:

Business requirements
-> Technical requirements
-> Cloud provider capabilities

Business Requirements: Clarify the Current Business First

Business requirement discovery should focus on factors that affect architecture shape: core path, read/write pattern, consistency, state complexity, external dependencies, permission boundaries, and delivery constraints.

QuestionArchitecture Impact
What is the core business path?Determines module boundaries, API boundaries, and transaction boundaries
What is the main read/write pattern?Determines database, cache, search, and read/write splitting choices
How strong must data consistency be?Determines local transactions, eventual consistency, compensation, and distributed transaction approaches
Is business state complex?Determines basic CRUD, state machines, workflow engines, and event-driven design
Are there high-frequency external dependencies?Determines adapters, retries, idempotency, circuit breaking, and graceful degradation
Are permission and tenant boundaries complex?Determines Auth, RBAC, ABAC, Tenant Model, and resource isolation
Are files, search, or reporting needed?Determines object storage, search engines, OLAP, and async tasks
Is realtime interaction needed?Determines polling, SSE, WebSocket, MQ, and Redis Pub/Sub
What are the team and delivery constraints?Determines monolith, modular design, microservices, Kubernetes, Serverless, and managed services

Technical Requirements: Select Backend Capabilities

Technical requirements come from business requirements and non-functional load. First map business requirements to backend capabilities, then use performance, availability, scalability, and quantitative signals to judge whether the architecture needs to evolve.

From Business Requirements to Technical Capabilities

Requirement SignalTechnical CapabilityProblem Solved
Basic CRUDIngress layer, application service, Repository, databaseBasic data create, read, update, delete
Login, roles, resource ownershipAuth, RBAC, Tenant ModelIdentity, permission, tenant isolation
Files, attachments, exportObject Storage, Job QueueFile storage, async export
SearchSearch EngineComplex search, full-text search
Long workflowState Machine, Workflow EngineState recovery, retry, audit
Realtime progress / notificationSSE, WebSocket, MQRealtime updates, async notification
Third-party integrationAdapter, Signature Verification, Retry, IdempotencyRequest authenticity, deduplication, failure recovery
Complex business rulesDomain Model, DDD, business state machineRule centralization, state transitions, long-term evolution

From Non-Functional Requirements to Technical Capabilities

Technical NeedTechnical CapabilityUpgrade Signal
High performanceCache, indexes, async processing, rate limiting, hotspot isolationP95 / P99 latency increases, or CPU / DB / network becomes a bottleneck
High availabilityReplicas, health checks, backups, graceful degradation, circuit breakingSingle-instance failure affects core business
High scalabilityStateless services, queues, read/write splitting, horizontal scalingTraffic, data volume, or team size grows
High concurrency spikesRedis, MQ, queuing, idempotency designPeak traffic impacts the core path
Data growthIndexes, archiving, partitioning, read/write splitting, OLAPSlow queries, oversized tables, slower backup and recovery
ObservabilityLogs, Metrics, Tracing, AlertProduction issues cannot be diagnosed
SecurityWAF, KMS, IAM, auditPublic exposure, complex permissions, compliance requirements
Multi-environment deliveryConfig, Secrets, CI/CD, IaCDevelopment, staging, and production configs start to diverge

Architecture selection principles:

  1. Confirm the current bottleneck first, then choose components.
  2. New components must directly solve a clear problem.
  3. Component benefits must exceed their development, operations, and troubleshooting costs.
  4. Architecture complexity must match the team’s maintenance capability.
  5. Do not introduce heavyweight solutions before there is an actual problem.

Common mistakes:

  • Introducing Kafka, Kubernetes, and microservices before a high-concurrency problem appears.
  • Applying full DDD to a basic CRUD project.
  • Self-hosting too much infrastructure when the team lacks operations capacity.
  • Replacing architecture design with a list of cloud products.
  • Listing technical terms without explaining problems, costs, and suitable conditions.

Quantitative Signals

Architecture selection needs current load data and growth rate. The ranges below are experience-based references; real judgment depends on business type, API complexity, data model, instance size, and team maintenance capability.

MetricObservation TargetExperience-Based Judgment
QPS < 50Internal systems, admin dashboards, small content sitesMonolith + single database is usually enough; prioritize delivery speed, permission boundaries, and data correctness
QPS 50-300Normal SaaS, content systems, regular business APIsPrioritize indexes, slow query tuning, cache, and API latency
QPS 300-1000Online business with visible trafficEvaluate cache, rate limiting, async tasks, read/write splitting, and horizontal scaling
QPS 1000+High-concurrency ingress, campaign page, transaction entryNeed Redis, MQ, rate limiting, load testing, capacity planning, and graceful degradation
Peak QPS / average QPS > 5Flash sales, ticketing, push traffic, marketing campaignsNeed traffic buffering, queuing, hotspot isolation, and ingress rate limiting
P95 latency > 300msUser-facing APIsCheck slow SQL, external calls, lock waits, serialization, and network latency
P99 latency > 1sCore APIs with obvious tail latencyNeed timeout control, retry control, circuit breaking, async processing, and resource isolation
Error rate > 0.1%-1%APIs, jobs, message consumptionNeed alerts, rate limiting, graceful degradation, rollback, and failure compensation
DB CPU stays above 70%Primary database, read replica, analytics databaseCheck slow queries, indexes, connection count, and cache hit rate before scaling
DB connections approach the limitApplication-to-database pathNeed connection pool tuning, slow request tuning, read/write splitting, or rate limiting
Redis hit rate is below expectationCache pathCheck key design, expiration strategy, cache misses, cache stampedes, and hot keys
MQ backlog keeps growingAsync jobs, orders, notifications, exportsConsumption capacity is insufficient; scale workers, split tasks, rate-limit entry, or optimize consumers
Single table reaches tens of millions of rowsCore business tableWatch indexes, archiving, partitioning, hot/cold data split, and backup recovery time
Single table reaches hundreds of millions of rowsHigh-growth transaction, log, or ledger tableNeed sharding, archiving, search engine, OLAP, or an independent data path

Quantitative signals identify the current bottleneck. If the database is slow, check slow queries and indexes first. If spikes are the problem, check rate limiting and traffic buffering. If jobs accumulate, check consumer capacity. If issues are invisible, add logs, metrics, and tracing first.

Cloud Provider Capabilities: Decide Managed or Self-Managed

Cloud provider capabilities are managed implementations of infrastructure capabilities. Selection should start from the needed capability, then decide whether to use a managed service or operate it yourself.

CapabilitySelf-Managed OptionManaged Cloud OptionSuitable Conditions
Static resource accelerationNginx, static serverCDNImages, JS/CSS, downloads, campaign pages
Load balancingNginx, HAProxy, EnvoyALB / CLB / ELBMulti-instance entry, cross-AZ traffic distribution
Relational databaseSelf-managed MySQL / PostgreSQLRDS, Cloud SQL, AuroraNormal business data, transaction data, permission data
CacheSelf-managed Redis / Redis ClusterManaged Redis, ElastiCacheHot data, sessions, rate limiting, ranking
Message queueKafka, RabbitMQ, RocketMQSQS, Pub/Sub, EventBridge, MSKAsync traffic buffering, event-driven design, task decoupling
Object storageLocal disk, MinIOS3, OSS, COS, GCSImages, attachments, exported files, backups
Container runtimeSelf-managed KubernetesEKS, GKE, ACK, Cloud RunMulti-service deployment, elastic scaling, rolling releases
SecuritySelf-managed WAF, certificates, key management systemWAF, KMS, IAM, Secrets ManagerPublic services, permission isolation, secret management, audit
ObservabilityPrometheus, Grafana, ELK, LokiCloudWatch, Cloud Logging, Cloud MonitoringLogs, metrics, alerts, tracing

Small teams and early-stage projects usually prefer managed services to reduce installation, upgrade, backup, disaster recovery, and incident recovery costs. For core transaction paths, check SLA, rate limits, backup restore, cross-AZ capability, failover time, and cost model.

Self-managed infrastructure mainly applies to cost control, compliance requirements, multi-cloud deployment, stronger control, or extreme performance requirements. Before choosing self-management, confirm that the team can handle deployment, upgrades, monitoring, backups, scaling, incident recovery, and security hardening.