shape

Dodam - Migrating the Architecture from Monolithic to MSA

Overview

Eliminating inter-service coupling and deployment inefficiencies while building a K3s cluster

Tech Stack

  • Java

    Java

  • Kotlin

    Kotlin

  • Spring Boot

    Spring Boot

  • Spring JPA

    Spring JPA

  • Spring Cloud Gateway

    Spring Cloud Gateway

  • MySQL

    MySQL

  • Redis

    Redis

  • Flyway

    Flyway

  • Kafka

    Kafka

  • gRPC

    gRPC

  • Docker Compose

    Docker Compose

  • AWS

    AWS

  • Kubernetes

    Kubernetes

Team

9 members (2 Backend, 3 Web, 2 Android, 2 iOS)

Period

2025.03 ~ 2026.03

Links

Backend Source CodeWeb Service

Details

  1. 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.
    Overview 1
  2. 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.
  3. 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.
  4. 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.
    Reducing the Deployment and Operational Complexity of Many Services 1
  5. 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.
    Backend Infrastructure 1
  6. 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.
  7. 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.