Integration Services Explained — What they are, when to use them, and how they behave
If you’ve been building with ABP for a while, you’ve probably used Application Services for your UI and APIs in your .NET and ASP.NET Core apps. Integration Services are similar—but with a different mission: they exist for service-to-service or module-to-module communication, not for end users.
If you want the formal spec, see the official doc: Integration Services. This post is the practical, no-fluff guide.
What is an Integration Service?
An Integration Service is an application service or ASP.NET Core MVC controller marked with the [IntegrationService] attribute. That marker tells ABP “this endpoint is for internal communication.”
- They are not exposed by default (safer for reusable modules and monoliths).
- When exposed, their route prefix is
/integration-api(so you can easily protect them at your gateway or firewall). - Auditing is disabled by default for them (less noise for machine-to-machine calls).
Quick look:
[IntegrationService]
public interface IProductIntegrationService : IApplicationService
{
Task<List<ProductDto>> GetProductsByIdsAsync(List<Guid> ids);
}
public class ProductIntegrationService : ApplicationService, IProductIntegrationService
{
public Task<List<ProductDto>> GetProductsByIdsAsync(List<Guid> ids)
{
// fetch and return minimal product info for other services/modules
}
}
Are they HTTP endpoints?
- By default: no (they won’t be reachable over HTTP in the ASP.NET Core routing pipeline).
- If you need them over HTTP (typically for microservices), explicitly enable:
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ExposeIntegrationServices = true;
});
Once exposed, ABP puts them under /integration-api/... instead of /api/... in the ASP.NET Core routing pipeline. That’s your hint to restrict them from public internet access.
Enable auditing (optional)
If you want audit logs for integration calls, enable it explicitly:
Configure<AbpAuditingOptions>(options =>
{
options.IsEnabledForIntegrationServices = true;
});
When should you use Integration Services?
- Internal, synchronous operations between services or modules.
- You need a “thin” API designed for other services (not for UI): minimal DTOs, no view concerns, predictable contracts.
- You want to hide these endpoints from public clients, or only allow them inside your private network or k8s cluster.
- You’re packaging a reusable module that might be used in both monolith and microservice deployments.
When NOT to use them
- Public APIs or anything intended for browsers/mobile apps → use regular application services/controllers.
- Asynchronous cross-service workflows → consider domain events + outbox/inbox; use Integration Services for sync calls.
- Complex, chatty UI endpoints → those belong to your external API surface, not internal integration.
Common use-cases and examples
- Identity lookups across services: an Ordering service needs basic user info from the Identity service.
- Permission checks from another module: a CMS module asks a Permission service for access decisions.
- Product data hydrations: a Cart service needs minimal product details (price, name) from Catalog.
- Internal admin/maintenance operations that aren’t meant for end users but are needed by other services.
Example: microservice-to-microservice call
- Mark and expose the integration service in the target service:
[IntegrationService]
public interface IUserIntegrationService : IApplicationService
{
Task<UserBriefDto?> FindByIdAsync(Guid id);
}
Configure<AbpAspNetCoreMvcOptions>(o => o.ExposeIntegrationServices = true);
- In the caller service, add an HTTP client proxy only for Integration Services if you like to keep things clean:
services.AddHttpClientProxies(
typeof(TargetServiceApplicationModule).Assembly,
remoteServiceConfigurationName: "TargetService",
asDefaultServices: true,
applicationServiceTypes: ApplicationServiceTypes.IntegrationServices);
- Call it just like a local service (ABP’s HTTP proxy handles the wire):
public class OrderAppService : ApplicationService
{
private readonly IUserIntegrationService _userIntegrationService;
public OrderAppService(IUserIntegrationService userIntegrationService)
{
_userIntegrationService = userIntegrationService;
}
public async Task PlaceOrderAsync(CreateOrderDto input)
{
var user = await _userIntegrationService.FindByIdAsync(CurrentUser.GetId());
// validate user status, continue placing order...
}
}
Monolith vs. Microservices
- Monolith: keep them unexposed and call via DI in-process. You get the same clear contract with zero network overhead.
- Microservices: expose them and route behind your gateway. The
/integration-apiprefix makes it easy to firewall/gateway-restrict.
Practical tips
- Keep integration DTOs lean and stable. These are machine contracts—don’t mix UI concerns.
- Name them clearly (e.g.,
UserIntegrationService) so intent is obvious. - Guard your ASP.NET Core gateway application: block
/integration-api/*from public traffic. - Enable auditing only if you truly need the logs for these calls.
Further reading
- Official docs: Integration Services
That’s it! Integration Services give you a clean, intentional way to design internal APIs—great in monoliths, essential in microservices.
Comments
maruusa 19 weeks ago
Integration services are components or platforms that enable various software systems to “talk” to each other—exchanging data, synchronizing processes, and automating tasks. Geometry Dash