docs/en/Blog-Posts/2026-04-01 v10_3_Preview/POST.md
We are happy to release ABP version 10.3 RC (Release Candidate). This blog post introduces the new features and important changes in this new version.
Try this version and provide feedback for a more stable version of ABP v10.3! Thanks to you in advance.
You can check the Get Started page to see how to get started with ABP. You can either download ABP Studio (recommended, if you prefer a user-friendly GUI application - desktop application) or use the ABP CLI.
By default, ABP Studio uses stable versions to create solutions. Therefore, if you want to create a solution with a preview version, first you need to create a solution and then switch your solution to the preview version from the ABP Studio UI:
There are no explicitly marked breaking changes in this version. However, there are still some important migration notes for specific scenarios. Please check the migration guide if you are upgrading from v10.2 or earlier: ABP Version 10.3 Migration Guide.
In this section, I will introduce some major features released in this version. Here is a brief list of titles explained in the next sections:
private_key_jwt Client Authentication + abp generate-jwksFindMany* / GetMany*)Volo.Abp.LuckyPenny.AutoMapper Providerprivate_key_jwt Client Authentication + abp generate-jwksABP v10.3 introduces end-to-end support for OpenIddict private_key_jwt client authentication.
Instead of using a shared client_secret, clients can now authenticate with an asymmetric key pair: keep the private key on the client, and register the public key (JWKS) on the authorization server.
On the open-source side, ABP CLI now includes the abp generate-jwks command (and the OpenIddict demo was updated accordingly). On the Pro side, OpenIddict application management now supports storing and validating JWKS for confidential applications.
This is especially useful for machine-to-machine and compliance-focused environments where shared secrets are not preferred.
Example - Generate a JWKS with ABP CLI:
abp generate-jwks --alg RS256 --key-size 2048 -o ./keys -f my-client
See the community article Secure Client Authentication with private_key_jwt in ABP 10.3 for a full walkthrough. This approach is especially useful for Pro solutions that manage confidential clients in the administration UI.
ABP v10.3 adds string-based publishing and subscription APIs for event-driven integrations.
When you do not know event types at compile time, you can now publish and handle events by name without introducing extra wrapper contracts up front. This is especially useful for plugin ecosystems, partner integrations, and metadata-driven application flows.
This is not a separate eventing model. Dynamic events run through the same ABP infrastructure (including outbox/inbox when configured), can be handled through DynamicEventData, and can coexist with typed handlers for the same event name. Distributed providers support this approach except Dapr, which requires startup-time topic declarations.
Example - Publish by event name:
await _distributedEventBus.PublishAsync(
"OrderPlaced",
new { OrderId = input.Id, CustomerEmail = input.Email }
);
Example - Subscribe dynamically at runtime:
eventBus.Subscribe("PartnerOrderReceived",
new PartnerOrderHandler(context.ServiceProvider));
public class PartnerOrderHandler : IDistributedEventHandler<DynamicEventData>
{
public Task HandleEventAsync(DynamicEventData eventData)
{
// eventData.EventName + eventData.Data
return Task.CompletedTask;
}
}
See the community article Dynamic Events in ABP for details.
ABP v10.3 introduces Dynamic Background Jobs (IDynamicBackgroundJobManager) and Dynamic Background Workers (IDynamicBackgroundWorkerManager) for runtime registration and execution by name.
With these APIs, you can enqueue jobs with dynamic payloads, register handler delegates at startup, and add/update/remove recurring workers at runtime. This is especially useful for plugin architectures, metadata-driven workflows, and tenant-specific scheduling scenarios where task types are not known at compile time.
Dynamic background jobs work through ABP's existing typed job pipeline (including provider integrations), while dynamic workers support runtime schedule management (period/cron depending on provider).
Example - Enqueue a job by name with dynamic payload:
await _dynamicBackgroundJobManager.EnqueueAsync("emails", new
{
EmailAddress = input.CustomerEmail,
Subject = "Order Confirmed",
Body = $"Your order {input.OrderId} has been placed."
});
Example - Update worker schedule at runtime:
await workerManager.UpdateScheduleAsync(
"InventorySyncWorker",
new DynamicBackgroundWorkerSchedule { Period = 10000 } // 10s
);
See #25059 and the community article Dynamic Background Jobs and Workers in ABP for details.
The API definition endpoint can now optionally return richer metadata such as summary/description fields for controllers, actions, and parameters.
This is particularly useful for dynamic client generation, API explorers, and tooling that consumes ABP API metadata directly without requiring OpenAPI parsing.
See #25022 for details.
FindMany* / GetMany*)ABP v10.3 extends IEntityCache with batch retrieval APIs so you can resolve multiple entities in a single cache/database flow instead of looping over FindAsync/GetAsync.
It includes both list-based APIs (FindManyAsync / GetManyAsync) and dictionary-based APIs (FindManyAsDictionaryAsync / GetManyAsDictionaryAsync) so you can choose the shape that best matches your access pattern.
Example - List-based batch retrieval (preserves input order):
var ids = new List<Guid> { id1, id2, id1 };
var products = await _productCache.GetManyAsync(ids); // throws if any ID is missing
var productsOrNull = await _productCache.FindManyAsync(ids); // null for missing IDs
Example - Dictionary-based batch retrieval (fast lookup by ID):
var productsById = await _productCache.GetManyAsDictionaryAsync(ids);
var nullableProductsById = await _productCache.FindManyAsDictionaryAsync(ids);
if (nullableProductsById.TryGetValue(id1, out var product) && product != null)
{
// use product
}
All of these methods are optimized for bulk scenarios by internally batching cache misses via distributed cache multi-get/multi-add operations.
ABP v10.3 enhances Angular UX for shared-user multi-tenancy scenarios, including invitation flows, tenant switch UX, and related identity/account integrations.
This improves the out-of-the-box experience for applications using tenant user sharing.
See #25051 for details.
ABP v10.3 upgrades Angular to 21.2 and TypeScript to 5.9, bringing the Angular UI stack to the latest ABP-supported frontend baseline.
This helps you stay current with the modern Angular and TypeScript ecosystem while benefiting from newer compiler/tooling improvements and maintaining compatibility with the ABP Angular packages in this release.
See #25072 for details.
Volo.Abp.LuckyPenny.AutoMapper ProviderABP v10.3 introduces Volo.Abp.LuckyPenny.AutoMapper as a new optional provider integration for projects that want to use the LuckyPenny-maintained AutoMapper package.
The existing Volo.Abp.AutoMapper package remains unchanged, and migration is straightforward: replace AbpAutoMapperModule with AbpLuckyPennyAutoMapperModule in your module dependencies while keeping the same ABP-facing namespaces and APIs.
This update also addresses the AutoMapper 14.x vulnerability context (GHSA-rvv3-g6hj-g44x), and ABP documentation was expanded with installation, usage, and migration guidance. For more information, see the documentation: LuckyPenny AutoMapper Integration.
ABP Commercial v10.3 RC also includes notable account security hardening:
These changes are security-focused and are designed to be practical for real projects. Here are the key points and how you can tune them:
Example - Tune profile picture upload restrictions:
Configure<AbpProfilePictureOptions>(options =>
{
options.AllowedFileExtensions = new[] { ".jpg", ".jpeg", ".png" };
options.MaxFileSizeInBytes = 2 * 1024 * 1024; // 2 MB
});
Example - Override account operation rate-limiting policies:
Configure<AbpOperationRateLimitingOptions>(options =>
{
options.ConfigurePolicy(
AbpAccountOperationRateLimitPolicies.SendPasswordResetCode,
policy =>
{
policy.ClearRules();
policy.PerHour(5);
policy.PerDay(20);
});
});
See the community article Operation Rate Limiting in ABP Framework for conceptual guidance.
PermissionIntegrationController.IsGrantedAsync now uses HttpPost for large payload scenarios (#25177).Autofac.Extensions.DependencyInjection to 11.0.0 (#25190).As always, exciting articles have been contributed by the ABP community. I will highlight some of them here:
Thanks to the ABP Community for all the content they have published. You can also post your ABP related (text or video) content to the ABP Community.
This version comes with some new features and a lot of enhancements to the existing features. You can see the Road Map documentation to learn about the release schedule and planned features for the next releases. Please try ABP v10.3 RC and provide feedback to help us release a more stable version.
Thanks for being a part of this community!