I've been working with ABP vNext and noticed something about the GuidGenerator in DomainServices. When I inject IGuidGenerator into my DomainService, the default implementation used is SimpleGuidGenerator.Instance.
1 : What’s the design reason for choosing SimpleGuidGenerator as the default instead of the sequential one? 2 : Are there downsides to using SequentialGuidGenerator globally (e.g., database dependencies, distributed system issues)? 3 : What’s the ABP-idiomatic way to replace the default with SequentialGuidGenerator via DI? 4 : Is ABP’s built-in SequentialGuidGenerator recommended for production with large datasets and GUID primary keys?
Thanks for your insights!
3 Answer(s)
-
0
- Solution
Default choice and design reason
- In ABP, IGuidGenerator.Create() is intended to avoid Guid.NewGuid() and provide DB-friendly GUIDs. The official guideline explicitly says “never use Guid.NewGuid() to create Ids” and recommends sequential GUIDs for performance on clustered indexes. ABP’s infrastructure documentation states that IGuidGenerator creates sequential GUIDs and that SequentialGuidGenerator is the default. If you’re seeing SimpleGuidGenerator.Instance in a DomainService, that indicates a local override or a custom registration, not the ABP default behavior. The design goal is: by default, ABP uses a sequential generator to reduce fragmentation and improve insert performance on relational databases.
Downsides or caveats of using sequential GUIDs globally
- Sequential GUIDs are designed to be monotonically increasing (in a DB-appropriate way) to reduce index fragmentation on clustered PKs. They are generally favorable for SQL Server clustered indexes compared to random GUIDs. Potential caveats:
- Predictability: IDs roughly encode creation order. If you consider that sensitive, it’s a trade-off.
- Cross-database ordering differences: Sequential GUID strategies differ by provider (e.g., SQL Server uses SequentialAtEnd style). ABP’s sequential generator handles this so it’s not typically a problem, but be aware IDs won’t be strictly comparable across providers if you mix them.
- No known distributed-system uniqueness downside: They remain 128-bit GUIDs and are safe for distributed generation. There’s no distributed-system uniqueness penalty compared to random GUIDs.
- Sequential GUIDs are designed to be monotonically increasing (in a DB-appropriate way) to reduce index fragmentation on clustered PKs. They are generally favorable for SQL Server clustered indexes compared to random GUIDs. Potential caveats:
How to replace the default with SequentialGuidGenerator via DI (ABP-idiomatic)
- If your app somehow resolved to SimpleGuidGenerator, override the registration in your module:
using Microsoft.Extensions.DependencyInjection; using Volo.Abp; using Volo.Abp.Guids; public class MyModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddSingleton<IGuidGenerator, SequentialGuidGenerator>(); } }This forces the sequential implementation globally. In an ABP app with standard EF Core provider packages, this is normally unnecessary because ABP already wires SequentialGuidGenerator as the default.
Is ABP’s SequentialGuidGenerator recommended for production with large datasets and GUID PKs?
- Yes. This is the documented recommendation specifically to mitigate heavy insert fragmentation on clustered indexes when using GUID PKs. For SQL Server, this is the preferred approach vs. Guid.NewGuid(). It is production-ready and the recommended default.
- Sources
- https://abp.io/docs/latest/framework/infrastructure/guid-generation
- https://github.com/abpframework/abp
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
-
0
thanks for your reply! But I’m confused — according to the ABP Vnext source code for DomainService, the default IGuidGenerator is explicitly set to SimpleGuidGenerator.Instance, not SequentialGuidGenerator:
public abstract class DomainService : IDomainService { public IAbpLazyServiceProvider LazyServiceProvider { get; set; } = default!;
[Obsolete("Use LazyServiceProvider instead.")] public IServiceProvider ServiceProvider { get; set; } = default!; protected IClock Clock => LazyServiceProvider.LazyGetRequiredService<IClock>(); protected IGuidGenerator GuidGenerator => LazyServiceProvider.LazyGetService<IGuidGenerator>(SimpleGuidGenerator.Instance); protected ILoggerFactory LoggerFactory => LazyServiceProvider.LazyGetRequiredService<ILoggerFactory>(); protected ICurrentTenant CurrentTenant => LazyServiceProvider.LazyGetRequiredService<ICurrentTenant>(); protected IAsyncQueryableExecuter AsyncExecuter => LazyServiceProvider.LazyGetRequiredService<IAsyncQueryableExecuter>(); protected ILogger Logger => LazyServiceProvider.LazyGetService<ILogger>(provider => LoggerFactory?.CreateLogger(GetType().FullName!) ?? NullLogger.Instance);}
This code shows that if IGuidGenerator isn’t resolved from DI, it falls back to SimpleGuidGenerator. But you mentioned ABP "already wires SequentialGuidGenerator as the default".
Could you clarify: Does ABP automatically register SequentialGuidGenerator as the IGuidGenerator implementation in DI (overriding the SimpleGuidGenerator fallback in DomainService)? If DI registration takes precedence, why does DomainService explicitly set SimpleGuidGenerator as the fallback? In a standard ABP app (with EF Core), can I safely rely on the default DI registration for SequentialGuidGenerator, or do I need to manually replace the DomainService’s fallback? I want to confirm that production (large datasets, GUID PKs) is using SequentialGuidGenerator to avoid index fragmentation. Thanks again!
-
0
hi
Normally, the
IGuidGeneratorservice will always be resolved. Does your application not resolve it?Thanks