MuleSoft  

Service Discovery in Microservices

Introduction

Microservices architecture has become one of the most popular approaches in modern software development because it addresses many limitations of monolithic systems, such as scalability constraints, slow deployments, and tightly coupled codebases.

However, microservices also introduce new challenges. One of the most critical questions is:

How do services find and communicate with each other when their IP addresses and ports change frequently?

This is where Service Discovery becomes essential.

In this article, you will learn:

  • What service discovery is

  • How it works in microservices

  • Why service discovery is important

  • Key benefits of service discovery

  • Popular service discovery tools

  • Practical implementation options for ASP.NET Core (.NET)

What Is Service Discovery?

Service discovery is the process in distributed systems for dynamically locating services and enabling communication between them.

In a microservices environment:

  • Each service is deployed independently

  • Services may run in multiple instances

  • Services can scale up or down automatically

  • Instances may restart or move between servers

Because of this, a service’s network location (IP address and port) can change at any time.

Hardcoding service URLs such as:

https://localhost:5002/api/payment

makes the system fragile.

Instead, services communicate using logical names, for example:

payment-service

Service discovery resolves these logical names to actual network locations at runtime.

Why Service Discovery Is Needed in Microservices

In a monolithic application, modules communicate through direct method calls. In microservices, communication happens over the network.

Without service discovery, teams would need to manually manage:

  • Service URLs

  • IP address changes

  • Port changes

  • Scaling events

This approach does not scale and quickly becomes unmanageable in production environments.

How Service Discovery Works

Service discovery typically operates in two main steps.

1. Service Registration

When a microservice starts, it registers itself with a service registry by providing:

  • Service name

  • IP address

  • Port

  • Health check endpoint

  • Optional metadata

The registry maintains an up-to-date list of all available service instances.

2. Service Lookup (Discovery)

When a service needs to call another service, it queries the registry:

Where is payment-service running?

The registry responds with the network addresses of one or more healthy instances. The calling service then connects to one of those instances.

Benefits of Service Discovery in Microservices

1. Dynamic Scalability

Microservices can scale automatically.

Example:

  • PaymentService scales from one instance to five instances

  • The service registry updates automatically

  • No configuration changes are required

2. Resilience

Failures are inevitable in distributed systems. Service discovery improves resilience by routing traffic only to healthy service instances when failures occur.

3. Load Balancing

Most service discovery systems integrate with load balancing. Requests are automatically distributed across multiple instances of a service.

4. Decentralized Communication

Services communicate using logical names instead of physical addresses, such as:

  • order-service

  • payment-service

  • inventory-service

5. Polyglot Support

Microservices are often built using multiple languages and frameworks. Service discovery works across platforms such as:

  • .NET

  • Java

  • Node.js

  • Python

Types of Service Discovery

1. Client-Side Discovery

In client-side discovery:

  • The calling service queries the service registry

  • The calling service selects an instance to communicate with

Common tools include:

  • Consul

  • Eureka

2. Server-Side Discovery

In server-side discovery:

  • The client sends a request to a gateway or load balancer

  • The gateway queries the service registry

  • The gateway routes the request to a healthy instance

Examples include:

  • Kubernetes service discovery

  • API gateways such as Nginx

Service Discovery in ASP.NET Core: Practical Options

In real-world .NET microservices, service discovery is commonly implemented using one of the following approaches.

Option 1: Kubernetes Built-in Service Discovery (Recommended)

If your services run inside Kubernetes, service discovery is provided out of the box.

Example:

If you create a Kubernetes service named:

payment-service

Other services can call it using:

http://payment-service

Kubernetes automatically routes traffic to healthy instances.

Option 2: Consul Service Discovery (VM or Docker Environments)

If you are not using Kubernetes, Consul is a popular choice for service discovery in ASP.NET Core applications.

Consul provides:

  • Service registry

  • Health checks

  • Service lookup

  • Optional service mesh capabilities

Implementing Service Discovery in ASP.NET Core Using Consul

Below is a simple and practical implementation example.

Step 1: Install the Consul NuGet Package

dotnet add package Consul

Step 2: Add Configuration in appsettings.json

{
  "Consul": {
    "Address": "http://localhost:8500",
    "ServiceName": "order-service",
    "ServiceId": "order-service-1",
    "ServiceAddress": "localhost",
    "ServicePort": 5001
  }
}

Step 3: Add a Health Check Endpoint

using Microsoft.AspNetCore.Mvc;

[ApiController]
public class HealthController : ControllerBase
{
    [HttpGet("/health")]
    public IActionResult Health()
    {
        return Ok("Healthy");
    }
}

Step 4: Register the Service in Program.cs

using Consul;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

var app = builder.Build();

app.MapControllers();

app.Lifetime.ApplicationStarted.Register(() =>
{
    var consulConfig = builder.Configuration.GetSection("Consul");

    var consulClient = new ConsulClient(c =>
    {
        c.Address = new Uri(consulConfig["Address"]);
    });

    var registration = new AgentServiceRegistration
    {
        ID = consulConfig["ServiceId"],
        Name = consulConfig["ServiceName"],
        Address = consulConfig["ServiceAddress"],
        Port = int.Parse(consulConfig["ServicePort"]),
        Check = new AgentServiceCheck
        {
            HTTP = $"http://{consulConfig["ServiceAddress"]}:{consulConfig["ServicePort"]}/health",
            Interval = TimeSpan.FromSeconds(10),
            Timeout = TimeSpan.FromSeconds(5)
        }
    };

    consulClient.Agent.ServiceRegister(registration).Wait();
});

app.Run();

Step 5: Run Consul

If Consul is running, open the Consul UI:

http://localhost:8500

Your microservice will now appear in the services list.

Conclusion

Service discovery is a foundational component of microservices architecture. Because microservices are dynamic and constantly changing, service discovery enables reliable communication without hardcoding network addresses.

For ASP.NET Core microservices, the most common service discovery approaches are:

  • Kubernetes built-in service discovery

  • Consul-based service discovery

Both approaches provide scalability, resilience, and load balancing support for modern distributed systems.