Dodam - Migrating the Architecture from Monolithic to MSA
Overview
Eliminating inter-service coupling and deployment inefficiencies while building a K3s cluster
Tech Stack

Java

Kotlin
Spring Boot

Spring JPA

Spring Cloud Gateway

MySQL

Redis

Flyway

Kafka

gRPC

Docker Compose

AWS
Kubernetes
Team
9 members (2 Backend, 3 Web, 2 Android, 2 iOS)
Period
2025.03 ~ 2026.03
Details
Overview
- Dodam is an in-school smart school platform with over 500 users. Tasks that were previously handled manually one by one (overnight-leave approvals, late-night self-study applications, academic schedule management, etc.) are now handled through Dodam.
- Developed and maintained the service server, which handled up to 162.82k requests over 30 days, averaging 5.4k requests per day.
- The web service is available only to students within the school.

Limitations of the Monolith and the Move to MSA
- Experienced problems with inter-service coupling and deployment inefficiency in the existing single application.
- Because all domains shared resources within a single process, a failure in one domain affected the entire system.
- There was a structural limitation in which even small changes required a full build and redeployment.
- Split the application into 11 services along domain boundaries and placed Spring Cloud Gateway as a single entry point to handle routing and OAuth2 authentication.
Designing the Communication Architecture for Service Separation
- As services were separated, logic previously handled through method calls had to be replaced with network communication.
- Applied gRPC for authentication flows that require an immediate response, and Kafka for events that need no waiting for a result (user creation, notification dispatch, etc.).
- Defined event schemas and topics commonly in the Core module to unify the message contracts between services.
- This enabled a polyglot architecture in which different languages could be used per service.
Reducing the Deployment and Operational Complexity of Many Services
- As the number of services grew, building and deploying everything each time became inefficient.
- Applied a Delta Build that detects and builds only changed services, along with per-service sequential rolling updates.
- Set up a K3s cluster (2 worker nodes) and distributed replicas only across the core services with concentrated traffic (Gateway, Auth, User), securing high availability within a limited infrastructure.

Backend Infrastructure
- Core features are handled by a Spring Boot server, and high-traffic APIs are cached using Redis.
- To support OAuth with a Dodam account, we run services such as a Token server, an OAuth server, and an OpenAPI server.

CI/CD Architecture
- When a PR is created, GitHub Actions automatically runs the Gradle build and tests to verify code quality.
- On merge into the develop branch, a Docker image is built and deployed to the development server via Docker Compose.
- On merge into the main branch, a Docker image is built and deployed to production on the K3s cluster via kubectl apply.
Reflections
- By operating a service used by the entire student body and responding quickly and accurately to feature requests and incidents, I came to appreciate the importance of a stable service and worked to improve code quality and maintainability.
- Through the move to MSA, I could selectively scale out only the services with concentrated traffic, which made me realize how much independent, service-level scaling improves operational efficiency.