1. Direct HTTP/REST Communication Between Microservices
- 
Each microservice exposes HTTP APIs.
 - 
Other services call those APIs directly when needed.
 - 
Example (Service A calls Service B):
 
Pros:
- 
Simple to implement.
 - 
No extra infrastructure required.
 
Cons:
- 
Tight coupling: Service A depends on Service B being up.
 - 
Latency: Each call adds network overhead.
 - 
Harder to scale with many services.
 
2. Shared Database Communication
- 
Microservices write events or data to a shared database table.
 - 
Other microservices poll or read changes periodically.
 - 
Example:
- 
Service A writes a “TaskCompleted” row in
Eventstable. - 
Service B periodically checks for new rows and processes them.
 
 - 
 
Pros:
- 
No external message broker needed.
 - 
Simple for small systems.
 
Cons:
- 
Polling can waste resources.
 - 
Hard to scale and maintain.
 - 
Not truly event-driven (eventual consistency).
 
3. In-Memory Event Bus
- 
If microservices run in same process or container, you can implement an in-memory event bus.
 - 
Example: Using Mediator pattern in .NET:
 
Pros:
- 
Very fast.
 - 
No infrastructure required.
 
Cons:
- 
Works only within a single application/process.
 - 
Cannot scale across multiple servers.
 
4. File-Based or Shared Memory
- 
Services write messages to a shared file or memory.
 - 
Other services monitor the file or memory to read messages.
 - 
Rarely used; mostly for legacy or highly constrained environments.
 
Cons:
- 
Complex, error-prone.
 - 
Not scalable.
 
✅ Key Points When Avoiding Brokers
- 
Synchronous REST calls are simplest but couple services.
 - 
Shared DB or in-memory events can simulate async communication but have limitations.
 - 
For distributed, scalable systems, eventually you’ll hit limitations without a broker.
 
💡 Tip:
If you really want no external tool, the most practical approach is a REST API + polling or callback mechanism. You can even implement a custom lightweight event bus over HTTP for async messaging between microservices.