DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

How does AI transform chaos engineering from an experiment into a critical capability? Learn how to effectively operationalize the chaos.

Data quality isn't just a technical issue: It impacts an organization's compliance, operational efficiency, and customer satisfaction.

Are you a front-end or full-stack developer frustrated by front-end distractions? Learn to move forward with tooling and clear boundaries.

Developer Experience: Demand to support engineering teams has risen, and there is a shift from traditional DevOps to workflow improvements.

Related

  • How I Made My Liberty Microservices Load-Resilient
  • Why Cloud Matters: Building Global, Scalable Microservices
  • Navigating the Maze: Evolving Projects and Database Dilemmas
  • Optimizing Database Connectivity: A Comparative Analysis of Tomcat JDBC vs. HikariCP

Trending

  • What They Don’t Teach You About Starting Your First IT Job
  • How to Improve Software Architecture in a Cloud Environment
  • OTel Me Why: The Case for OpenTelemetry Beyond the Shine
  • Guide to Repairing Damaged Apache Doris Tablets
  1. DZone
  2. Software Design and Architecture
  3. Microservices
  4. Defining Effective Microservice Boundaries - A Practical Approach To Avoiding The Most Common Mistakes

Defining Effective Microservice Boundaries - A Practical Approach To Avoiding The Most Common Mistakes

Most microservices failures stem from poor boundaries. Fix those, and your teams will ship faster, suffer less and succeed more.

By 
Mohit Menghnani user avatar
Mohit Menghnani
·
Jun. 09, 25 · Analysis
Likes (2)
Comment
Save
Tweet
Share
963 Views

Join the DZone community and get the full member experience.

Join For Free

Have you found yourself staring at an entire whiteboard filled with boxes and arrows, pondering whether this would become the next awesome microservices architecture or the worst distributed monolith that ever existed? Same here, and more often than I would like to admit.

Last month, I was talking to one of my cofounder friends, and he mentioned, “We have 47 services!” with pride. Then two weeks later, I was going through their docs and found out that to deploy a simple feature, I need to make changes in six of their services. What I thought was their “microservices” architecture turned out to be a monolith split into pieces, with distribution complexity but no benefits whatsoever.

Perhaps the most critically important and the most underappreciated step in this architectural style is correct partitioning of microservices. Doing so increases modular independent deployability, isolation of faults, and swiftness in team operations. Mess it up, and welcome to a distributed system that is a thousand times harder to maintain than the monolith you wanted to remove.

The Anti-patterns: How Boundaries Fail – Consider the Case 

The Distributed Monolith: Death by a Thousand Cuts

An application made up of multiple services that are interdependent is an example of a pattern I encounter frequently, known as “distributed monolith.” This occurs when the complexity of distribution exists, but not the advantages.

Here are some indicators that your distributed Monolith is operating below peak efficiency:

  • One modification prompts and requires multiple adaptations across different services.
  • Disabling dependency across services results in a breakage.
  • Cross-team coordination complexity for release planning.

A team I recently interacted with had to cross-coordinate across eight services for deployment just to add a field in their user’s profile. That is neither a microservices nor a service; that is just an unnecessarily intricate web of self-ensuing torture.

The Shared Database Trap

Again, “We need to use the same data!” falls under an alarm that can lead to this trap. Having many services access the same database tables leads to direct hidden coupling that eliminates every siloed advantage your architecture stands for.

I saw a retail company suffering through Black Friday as a consequence of four hours of downtime when their order service’s inventory service changed a database schema that their order service relied on.

Nanoservice Growth: Over-Indulging on the Good Stuff

This can also go in the opposite direction. Sometimes I refer to it as “nanoservice madness.” You create an endless number of services and it turns your architecture into something resembling spaghetti.

One of the gaming companies I consulted for was creating individual microservices for user achievements, user added preferences, user friends, and even user authentication and profile. Each of these services had their own deployment pipeline, database, and even an on-call rotation. The operational overhead was too much for their small team.

A Defined Scenario: Redesigning an E-Commerce Boundary

Let me show you an actual scenario from last year. I was consulting for an e-commerce business that had a typical case of a “distributed monolith.” Their initial architecture was something along the lines of this:

YAML
 
# Original architecture with poor boundaries
services:
  product-service:
    responsibilities:
      - Management of product catalogs
      - Inventory management
      - Rules associated with pricing
      - Discount calculations
    database: shared_product_db
    dependencies:
      - user-service
      - order-service

  order-service:
    responsibilities:
      - Management and creation of orders
      - Processing of payments
      - Coordination of shipping
    database: shared_order_db
    dependencies:
      - product-service
      - user-service

  user-service:
    responsibilities:
      - User profiles
      - Authentication
      - Authorization
      - User preferences
    database: shared_user_db
    dependencies:
      - product-service


It was obvious what the problems were. Services did have an appropriate amount of responsibilities but were overloaded with circular dependencies and too much knowledge of each other. Changes required coordinating at minimum three separate teams which is a disaster waiting to happen.

Their business professionals were with us for a week. By the end of day one, the sticky notes had taken over the walls. The product team was in a heated debate with the inventory folks over who “owned” the concept of a product being “in stock.” It was chaotic, but by the end of the week, we had much clearer boundaries.

The end result is as follows:

YAML
 
services:
  catalog-service:
    responsibilities:
      - Product information
      - Categorization
      - Search
    database: catalog_db
    dependencies: []

  inventory-service:
    responsibilities:
      - Stock tracking
      - Reservations
    database: inventory_db
    dependencies: []

  pricing-service:
    responsibilities:
      - Base prices
      - Discounts
      - Promotions
    database: pricing_db
    dependencies: []

  order-service:
    responsibilities:
      - Order creation
      - Tracking
      - History
    database: order_db
    dependencies:
      - catalog-service
      - inventory-service
      - pricing-service (all async)

  payment-service:
    responsibilities:
      - Payment processing
      - Refunds
    database: payment_db
    dependencies: []

  user-profile-service:
    responsibilities:
      - Profile management
      - Preferences
    database: user_profile_db
    dependencies: []

  auth-service:
    responsibilities:
      - Authentication
      - Authorization
    database: auth_db
    dependencies: []


I understand your initial thoughts, “You went from 3 services to 7? That is increasing complexity, not decreasing it,” right? The thing is, every service now has one, dedicated responsibility. The dependencies are reduced and mostly asynchronous. Each service is fully in control of its data.

The outcome was drastic. The average time to implement new features decreased by 60%, while deployment frequency went up by 300%. Their Black Friday sale was the real test for us six months later. Each service scaled on its load patterns rather than overstocking resources like the previous year. While the catalog service required 20 instances, payment only needed five. In the middle of the night, their CTO texted me a beer emoji, the universal sign of a successful launch.

A Practical Strategy Finding The Right Boundaries

Start With Domain-Driven Design (But Make It Work)

As much as Domain-Driven Design (DDD) purists would like to disagree, you don’t need to be a purist to benefit from DDD’s tools for exploring boundaries.

Start with Event Storming. This is a workshop approach where you gather domain experts and developers to construct business process models using sticky notes representing domain events, commands, and aggregates. This type of collaboration often exposes boundaries that are already a feature in your domain.

The “Two Pizza Team” Rule Still Works

Amazon continues to enforce their famous rule that states a team should be small enough to be fed by two pizzas. The team should be able to fit into a single meeting room alongside to microservices. If a service grows so complicated that it takes more than 5-8 engineers to maintain it, that's often an indication it should be split.

But the inverse is also true, if you have 20 services and only 5 engineers, there is an increasing likelihood you’ve become too fine grained.

The Cognitive Load Test Introduction 2025

An interesting approach I adopted in 2025 is what I like to refer to as 'the cognitive load test' for boundary determination, which seems to be very effective. It’s very straightforward: does any new team member manage to understand the goals, duties, and functions of the service within a day? If not, your service might have too many operations or is fragmented.

Actionable Insights for 2025 and Further

The Strangler Fig Pattern: Expand Your Horizons

When remodeling an existing system, don’t sweat the boundaries on the first attempt. Implement the Strangler Fig pattern which replaces parts of monolithic architecture gradually with well-structured microservices (named after a vine that gradually overtakes its host tree).

A healthcare client of mine tried to create the perfect microservices architecture for 18 months without writing a single line of code. Their design became completely obsolete after many changes within the business requirements during the tangled time-consuming process.

The Newest Pattern: Boundary Observability

A trend that I've started noticing in 2025 is something I'm calling “boundary-testing observability”—monitoring cross service dependencies and consistency data, essentially. ServiceMesh and BoundaryGuard are tools that will notify you when services are getting too talkative or when data redundancy is posing a consistency threat.

Concluding Remarks: Boundaries Are a Journey, Not a Destination

After assisting countless businesses with adopting microservices, my domain understanding boundaries have shifted as business needs change. This learning will always remain agile, and boundless.

If there’s a strong “value” in doing so, initiate with coarse-grained services and progress from there. Boundaries and borders are subjective. There is a fine line that dictates whether data should be shared or duplicated, so be reasonable. Most importantly, pay attention to the problems and pain your teams face, there is a strong chance that it will give clues to boundary issues.

As my mentor used to say, “the best microservices architecture isn’t the one that looks prettiest on a whiteboard—it’s the one that lets your teams ship features quickly and safely without wanting to quit every other Tuesday.”

Database Domain-driven design microservices

Opinions expressed by DZone contributors are their own.

Related

  • How I Made My Liberty Microservices Load-Resilient
  • Why Cloud Matters: Building Global, Scalable Microservices
  • Navigating the Maze: Evolving Projects and Database Dilemmas
  • Optimizing Database Connectivity: A Comparative Analysis of Tomcat JDBC vs. HikariCP

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: