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)

  1. 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.
  2. 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.
  3. 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.
  4. 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/).
  5. 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}");
}
}
Share this lesson: