Documentation Index Fetch the complete documentation index at: https://docs-mstore.faisalaffan.com/llms.txt
Use this file to discover all available pages before exploring further.
System Design & Architecture
Dokumentasi lengkap arsitektur sistem MStore Backend dari high-level design hingga implementation details.
π‘ Working with Diagrams:
Zoom : Cmd/Ctrl + Scroll atau klik kanan β βOpen Image in New Tabβ
Download : Copy code diagram β paste ke Mermaid Live Editor β Download PNG/SVG
Full Guide : Lihat Mermaid Guide untuk tutorial lengkap
π― Architecture Principles
MStore Backend dibangun dengan prinsip:
β
Clean Architecture : Separation of concerns (handler β service β repository)
β
Domain-Driven Design : Business logic organized by domain
β
Multi-Tenant : Merchant-scoped data isolation
β
Microservices-Ready : Modular design untuk future decomposition
β
Event-Driven : Message broker integration (NATS, RabbitMQ, Kafka)
β
API-First : RESTful API dengan OpenAPI/Swagger documentation
β
Observability : LGTM stack (Loki, Grafana, Tempo, Mimir)
ποΈ High-Level Architecture
π¦ Clean Architecture Layers
1. Handler Layer (Presentation)
Responsibility : HTTP request/response handling, validation, authentication
// internal/domains/transaction/transaction_handler.go
type TransactionHandler struct {
service TransactionService
}
func ( h * TransactionHandler ) CreateTransaction ( c * fiber . Ctx ) error {
// 1. Parse & validate request
var req CreateTransactionRequest
if err := c . BodyParser ( & req ); err != nil {
return response . BadRequest ( c , "invalid request" )
}
// 2. Get user context
userID := c . Locals ( "user_id" ).( string )
// 3. Call service
tx , err := h . service . CreateTransaction ( c . Context (), req , userID )
if err != nil {
return response . InternalError ( c , err . Error ())
}
// 4. Return response
return response . Success ( c , tx )
}
2. Service Layer (Business Logic)
Responsibility : Business rules, orchestration, transaction management
// internal/domains/transaction/transaction_service.go
type TransactionService interface {
CreateTransaction ( ctx context . Context , req CreateTransactionRequest , userID string ) ( * Transaction , error )
VerifyPayment ( ctx context . Context , txID int64 , req VerifyPaymentRequest ) ( * Transaction , error )
SyncTransaction ( ctx context . Context , txID int64 ) ( * Transaction , error )
}
type transactionService struct {
repo TransactionRepository
inventoryRepo InventoryRepository
accountingRepo AccountingRepository
paymentClient PaymentClient
}
func ( s * transactionService ) CreateTransaction ( ctx context . Context , req CreateTransactionRequest , userID string ) ( * Transaction , error ) {
// 1. Validate business rules
if err := s . validateTransaction ( req ); err != nil {
return nil , err
}
// 2. Begin transaction
return s . repo . Transaction ( ctx , func ( tx * gorm . DB ) ( * Transaction , error ) {
// 3. Create transaction
transaction := & Transaction {
BranchCode : req . BranchCode ,
CashierID : userID ,
Status : "draft" ,
Items : req . Items ,
GrandTotal : calculateTotal ( req . Items ),
}
if err := s . repo . Create ( ctx , transaction ); err != nil {
return nil , err
}
// 4. Generate transaction code
transaction . TransactionCode = s . generateTransactionCode ( transaction )
return transaction , nil
})
}
3. Repository Layer (Data Access)
Responsibility : Database operations, query building
// internal/domains/transaction/transaction_repository.go
type TransactionRepository interface {
Create ( ctx context . Context , tx * Transaction ) error
GetByID ( ctx context . Context , id int64 ) ( * Transaction , error )
Update ( ctx context . Context , id int64 , updates map [ string ] interface {}) error
Transaction ( ctx context . Context , fn func ( * gorm . DB ) error ) error
}
type transactionRepository struct {
db * gorm . DB
}
func ( r * transactionRepository ) Create ( ctx context . Context , tx * Transaction ) error {
return r . db . WithContext ( ctx ). Create ( tx ). Error
}
func ( r * transactionRepository ) GetByID ( ctx context . Context , id int64 ) ( * Transaction , error ) {
var tx Transaction
err := r . db . WithContext ( ctx ).
Preload ( "Items" ).
Preload ( "Items.Product" ).
First ( & tx , id ). Error
return & tx , err
}
π Domain Organization
internal/domains/
βββ auth/ # Authentication & Authorization
β βββ auth_handler.go
β βββ auth_service.go
β βββ auth_repository.go
β βββ auth_payload.go
β βββ auth_response.go
βββ transaction/ # POS Transactions
β βββ transaction_handler.go
β βββ transaction_service.go
β βββ transaction_repository.go
β βββ transaction_state.go # State machine
β βββ transaction_journal_mapping.go
βββ inventory/ # Inventory & Warehouse
β βββ inventory_handler.go
β βββ inventory_service.go
β βββ inventory_repository.go
βββ payments/ # Payment Gateway Integration
β βββ payment_service.go
β βββ xendit/
β β βββ xendit_service.go
β β βββ xendit_payload.go
β βββ midtrans/
βββ pos/ # POS Operations
β βββ pos_handler.go
β βββ pos_service.go
β βββ offline/ # Offline-first support
βββ approvals/ # Multi-level Approval
β βββ approval_handler.go
β βββ approval_service.go
β βββ approval_repository.go
βββ accounting/ # Journal & Financial
β βββ accounting_service.go
β βββ journal_repository.go
βββ product/ # Product & Bundle
βββ promotions/ # Promotions & Price Lists
βββ merchant/ # Merchant Management
βββ branches/ # Branch Management
βββ user/ # User Management
βββ index.go # Domain registry
π Request Flow
Typical API Request Flow
ποΈ Database Architecture
Multi-Database Strategy
MySQL (Primary - Transactional)
Transactions
Inventory & Warehouse
Approvals
Accounting & Journals
Master data (Products, Branches, Users)
MongoDB (Secondary - Flexible Schema)
POS offline transactions (temporary)
Audit logs
Analytics data
Unstructured documents
Redis (Cache & Session)
Session storage
API rate limiting
Real-time data cache
Pub/Sub for real-time updates
Multi-Tenant Data Isolation
-- Every table has merchant_id for isolation
CREATE TABLE transactions (
id BIGINT UNSIGNED PRIMARY KEY ,
merchant_id BIGINT UNSIGNED NOT NULL ,
branch_id BIGINT UNSIGNED,
transaction_code VARCHAR ( 255 ),
-- ... other columns
INDEX idx_merchant (merchant_id),
FOREIGN KEY fk_merchant (merchant_id)
REFERENCES merchants(id)
);
-- Application-level filtering
SELECT * FROM transactions
WHERE merchant_id = ?
AND branch_id = ?
AND deleted_at IS NULL ;
π Security Architecture
Authentication Flow
Authorization (RBAC)
// Middleware for role-based access
func RequireRole ( roles ... string ) fiber . Handler {
return func ( c * fiber . Ctx ) error {
userRole := c . Locals ( "user_role" ).( string )
for _ , role := range roles {
if userRole == role {
return c . Next ()
}
}
return response . Forbidden ( c , "insufficient permissions" )
}
}
// Usage in routes
app . Post ( "/api/v1/transactions/:id/void" ,
middleware . Auth (),
middleware . RequireRole ( "MANAGER" , "ADMIN" ),
handler . VoidTransaction ,
)
π‘ Event-Driven Architecture
Message Broker Integration
// Publish event after transaction created
func ( s * transactionService ) CreateTransaction ( ctx context . Context , req CreateTransactionRequest ) ( * Transaction , error ) {
// ... create transaction
// Publish event
event := TransactionCreatedEvent {
TransactionID : tx . ID ,
TransactionCode : tx . TransactionCode ,
MerchantID : tx . MerchantID ,
BranchID : tx . BranchID ,
Amount : tx . GrandTotal ,
CreatedAt : tx . CreatedAt ,
}
if err := s . messageBroker . Publish ( "transaction.created" , event ); err != nil {
// Log error but don't fail transaction
log . Printf ( "failed to publish event: %v " , err )
}
return tx , nil
}
// Subscribe to events
func ( s * inventoryService ) SubscribeToTransactionEvents () {
s . messageBroker . Subscribe ( "transaction.created" , func ( msg Message ) {
var event TransactionCreatedEvent
json . Unmarshal ( msg . Data , & event )
// Process inventory movement
s . ProcessTransactionInventory ( context . Background (), event )
})
}
π Observability Architecture
LGTM Stack Integration
Loki (Logs)
// Structured logging with Zap
logger . Info ( "transaction created" ,
zap . String ( "transaction_code" , code ),
zap . Int64 ( "merchant_id" , merchantID ),
zap . Float64 ( "amount" , amount ),
)
Tempo (Traces)
// OpenTelemetry tracing
ctx , span := tracer . Start ( ctx , "CreateTransaction" )
defer span . End ()
span . SetAttributes (
attribute . String ( "transaction.code" , code ),
attribute . Int64 ( "transaction.amount" , amount ),
)
Mimir (Metrics)
// Prometheus metrics
counter , _ := meter . Int64Counter ( "transactions.created" )
counter . Add ( ctx , 1 ,
metric . WithAttributes (
attribute . String ( "branch" , branchCode ),
attribute . String ( "payment_method" , "CASH" ),
),
)
Grafana (Dashboards)
Transaction volume & revenue
API latency & error rate
Database query performance
Cache hit rate
Message broker throughput
π Deployment Architecture
Development Environment
# docker-compose.yml
version : '3.8'
services :
app :
build : .
ports :
- "8080:8080"
environment :
- ENV=development
- DB_HOST=mysql
- REDIS_HOST=redis
depends_on :
- mysql
- redis
- nats
mysql :
image : mysql:8.0
environment :
MYSQL_ROOT_PASSWORD : root
MYSQL_DATABASE : mstore
volumes :
- mysql_data:/var/lib/mysql
redis :
image : redis:7-alpine
ports :
- "6379:6379"
nats :
image : nats:latest
ports :
- "4222:4222"
Production Architecture
Target Metrics
Metric Target Notes API Latency (P95) < 100ms Excluding external API calls API Latency (P99) < 500ms Including database queries Throughput 10k req/s Per instance Database Query < 50ms P95 for simple queries Cache Hit Rate > 80% Redis cache Availability 99.9% ~8.7 hours downtime/year Error Rate < 0.1% 4xx + 5xx errors
Scalability Strategy
Horizontal Scaling
Stateless application servers
Load balancer distribution
Database read replicas
Redis cluster for cache
Vertical Scaling
Database server resources
Cache memory allocation
Message broker capacity
Caching Strategy
L1: In-memory cache (per instance)
L2: Redis cluster (shared)
Cache invalidation via events
π‘ Best Practices
Follow clean architecture layers
Use dependency injection
Implement proper error handling
Log with structured logging (Zap)
Use context for cancellation & timeout
Implement circuit breaker for external APIs
Use database transactions for atomic operations
Implement idempotency for critical operations
Monitor with OpenTelemetry
Document APIs with Swagger
DONβT β
Jangan skip input validation
Jangan hardcode credentials
Jangan ignore context cancellation
Jangan block goroutines indefinitely
Jangan skip error logging
Jangan expose internal errors ke client
Jangan skip database indexes
Jangan ignore connection pooling
π Migration Strategy
Microservices Decomposition (Future)
Decomposition Strategy:
Start with bounded contexts (domains)
Extract stateless services first
Implement API gateway
Use event bus for inter-service communication
Gradual migration per domain
Tech Stack Library dan tools yang digunakan
Service Template Template untuk membuat service baru
API Styleguide Panduan API design & conventions
Database Schema ERD lengkap database
Observability LGTM stack setup & monitoring