How Tencent Docs Seamlessly Switches Between Monolith and Microservices

Tencent Docs tackles the trade‑offs of monolithic and microservice architectures by implementing a flexible, automated system that merges selected microservices into a few monoliths for private‑cloud scenarios, reducing runtime costs, deployment overhead, image size, memory usage and CPU consumption while preserving performance and scalability.

dbaplus Community
dbaplus Community
dbaplus Community
How Tencent Docs Seamlessly Switches Between Monolith and Microservices

1. Introduction: Architecture Challenges

Software architecture has no silver bullet; a good design must be continuously iterated. Tencent Docs faced the need to balance monolithic and microservice designs to meet diverse business scenarios, making its approach valuable for similar projects.

2. Balancing Monolith and Microservices

Microservices offer decoupling, isolation, and elasticity but bring high runtime, deployment, and image‑distribution costs, especially in private‑cloud deployments where only dozens to hundreds of users exist. A monolithic approach reduces these costs but risks losing microservice benefits. Tencent Docs therefore designed a flexible strategy that can merge many microservices into a few monoliths for private deployments while keeping a microservice layout for large‑scale C‑end scenarios.

3. Practice: Automated Switching Tool

The monolith tool automates service merging based on a YAML‑like configuration file that lists which microservices should be combined into each monolith module.

modules:
  - name: monolith-module1
    merged_servers:
      - name: microserver1
        ...
      - name: microserver2
        ...
  - name: monolith-module2
    merged_servers:
      - name: microserver3
        ...
      - name: microserver4
        ...

This configuration drives a CI pipeline that detects changes and generates the merged monolith code for each merge request.

Challenge 1: High Runtime, Deployment, and Image Costs

Each microservice runs its own tRPC‑Go runtime, consuming excessive memory and CPU, and each requires a separate container image (total >10 GB). Merging into monoliths eliminates redundant runtimes and reduces image size.

Challenge 2: Divergent Configurations

Microservices use varied configuration styles (local files vs. trpc_go.yaml plugins). A unified configuration component was created, and example configurations are shown below.

# Microservice config
plugin:
  config:
    app:
      providers:
        serverA:
          app.yaml:
            foo: bar
            foz: baz
# Monolith config
plugin:
  config:
    app:
      providers:
        serverA:
          app.yaml:
            foo: bar
            foz: baz
        serverB:
          app.yaml:
            zoo: bar
            zoz: baz
        ...

Plugin configuration conflicts were resolved by namespacing each service under the plugin key.

# Original plugin config (conflict)
plugin:
  type-foo:
    name-bar:
      key1: value1
      key2: value2
# Refactored plugin config (namespaced)
plugin:
  type-foo:
    name-bar:
      service1:
        key1: value1
        key2: value2
      service2:
        key1: value2
        key2: value1
      ...

Challenge 3: Global Variable Modifications

Modifying global variables such as http.DefaultServerCodec or restful.Marshaller in a microservice is safe, but in a monolith it can affect all merged services. Two strategies were adopted:

Strategy 1: Develop a common plugin that encapsulates required changes via a new cgi protocol (illustrated in the image below).

Strategy 2: Isolate services that need the same global modification into separate modules, preventing cross‑service impact.

Challenge 4: Hidden Bugs

Some bugs only surface after merging. Example:

func Register(s *server.Server) {
  someserverpb.RegisterSomeServerSomeService(s, newSomeServiceImpl())
}

In a monolith, the registration may overwrite previously registered services, causing 404 errors. The author recommends a “binary search‑style” debugging method to isolate the offending service.

Challenge 5: Continuous Changes

After merging, ongoing changes can break compatibility. Automated checks in each merge request verify that configuration and code still satisfy merging constraints, with plans to add interface and end‑to‑end tests.

4. Results: Benefits of the Monolith Architecture

Switching to a monolith dramatically reduces resource consumption. For a representative module (originally four microservices), the monolith version achieved:

Binary size: 68 MB vs. 264 MB (≈74% reduction)

Memory usage: 670 MB vs. 1 722 MB (≈61% reduction)

CPU usage: 4.99 cores vs. 6.43 cores (≈22% reduction)

Average request latency: 9.3 ms vs. 9.8 ms (≈5% reduction)

Extrapolating to full‑scale monolithization predicts a 75% drop in total image size and a 96% reduction in total memory consumption, while preserving the performance advantages of microservices.

The final generated template (simplified) looks like this:

// Code generated by backend/tools/monolith, DO NOT EDIT.
// Package service rpc entry layer.
package service

import (
    {{- range .MergedServers}}
    {{.}}service "docx/backend/application/{{.}}/service"
    {{- end}}
    "git.code.oa.com/trpc-go/trpc-go/server"
)

// Register registers pb service implementations.
func Register(s *server.Server) {
    {{- range .MergedServers}}
    {{.}}service.Register(s)
    {{- end}}
}

This concise implementation improves development efficiency, lowers maintenance cost, and enables flexible switching between monolithic and microservice deployments.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

architectureMicroservicesDeploymentmonolithtRPC
dbaplus Community
Written by

dbaplus Community

Enterprise-level professional community for Database, BigData, and AIOps. Daily original articles, weekly online tech talks, monthly offline salons, and quarterly XCOPS&DAMS conferences—delivered by industry experts.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.