Domain Driven Design
Context Mapping
Created: 10 Jan 2026
Updated: 10 Jan 2026
Open Host Service (OHS)
In Domain-Driven Design (DDD), Open Host Service (OHS) is a strategic pattern used to define a protocol that gives access to your subsystem as a set of services. It is typically implemented when one Upstream Bounded Context needs to be consumed by multiple Downstream contexts.
Instead of creating a custom integration for every new consumer, the provider defines a standardized, public interface.
Core Features of Open Host Service (OHS)
- Standardization: It provides a single, unified entry point for all consumers. Whether it's a mobile app, a third-party partner, or another internal microservice, they all use the same API.
- Published Language: OHS is almost always paired with a Published Language (like JSON, XML, or Protobuf). This defines the shared data contracts (DTOs) that everyone agrees to use.
- Decoupling: It protects the internal Domain Model. You can refactor your internal logic, database schema, or entity structures without breaking the consumers, as long as the OHS contract remains the same.
- Stability & Versioning: Since many systems depend on it, OHS focuses on backward compatibility. Changes are usually introduced through versioning (e.g.,
/api/v1/to/api/v2/). - Documentation: A true OHS is well-documented (e.g., via Swagger/OpenAPI), allowing downstream teams to integrate without constant "back-and-forth" communication with the upstream team.
Cinema Ticketing Example: OHS in Action
In a cinema system, the Booking Context serves as the Upstream provider. Many downstream systems want to reserve seats.
Microservice Example
public record BookingRequest(
Guid SessionId,
string SeatNumber,
string CustomerEmail
);
public record BookingResponse(
Guid TicketId,
string AccessCode,
DateTime ExpiryDate
);
app.MapPost("/api/v1/bookings/reserve", async (BookingRequest request, IBookingService bookingService) => {
// 1. İş kuralı: Koltuk uygun mu?
var isAvailable = await bookingService.CheckAvailability(request.SessionId, request.SeatNumber);
if (!isAvailable)
return Results.Conflict("this seat already reserved");
var ticket = await bookingService.CreateReservation(request);
return Results.Ok(new BookingResponse(
ticket.Id,
ticket.QRCode,
ticket.CreatedAt.AddMinutes(15) // Ödeme için 15 dk süre
));
})
.WithOpenApi()
Moduler Monolith Example
/src
/Modules
/Catalog
/Cinema.Modules.Catalog.Domain
/Cinema.Modules.Catalog.Infrastructure
/Cinema.Modules.Catalog.PublicApi (Contracts)
/Booking
/Cinema.Modules.Booking.Domain
/Cinema.Modules.Booking.Infrastructure
/Cinema.Modules.Booking.PublicApi (Contracts)
/Shared
/Cinema.Shared.Kernel (Events, Base classes)
/Host
/Cinema.API (The Monolith)
// In Cinema.Modules.Booking.PublicApi
namespace Cinema.Modules.Booking.PublicApi;
public interface IBookingModule
{
Task<BookingResponse> CreateReservationAsync(BookingRequest request);
}
public record BookingRequest(Guid ShowtimeId, string SeatNumber, string CustomerEmail);
public record BookingResponse(Guid TicketId, bool IsSuccess, string Message);
// In Cinema.Modules.Booking.Infrastructure
using Cinema.Modules.Booking.PublicApi;
internal class BookingModule : IBookingModule
{
private readonly IReservationRepository _repository;
public BookingModule(IReservationRepository repository)
{
_repository = repository;
}
public async Task<BookingResponse> CreateReservationAsync(BookingRequest request)
{
// Business Logic: Check if seat is available
// Save to Database
return new BookingResponse(Guid.NewGuid(), true, "Reservation confirmed.");
}
}
Event Example
// In Cinema.Shared.Kernel
public record TicketPurchasedEvent(Guid CustomerId, decimal Amount) : INotification;
// In Cinema.Modules.Booking (Publisher)
public class TicketService
{
private readonly IMediator _mediator;
public async Task Purchase(Guid customerId, decimal price)
{
// Purchase logic...
await _mediator.Publish(new TicketPurchasedEvent(customerId, price));
}
}
// In Cinema.Modules.Loyalty (Subscriber)
internal class TicketPurchasedHandler : INotificationHandler<TicketPurchasedEvent>
{
public async Task Handle(TicketPurchasedEvent notification, CancellationToken ct)
{
// Add points to customer's loyalty account
Console.WriteLine($"Adding points for customer: {notification.CustomerId}");
}
}