Open Closed

Why does GuidGenerator in DomainService use SimpleGuidGenerator.Instance? It seems to just wrap Guid.NewGuid() #10131


User avatar
0
kingdom created

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!


9 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    1. 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.
    • 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.
    1. 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.

  • User Avatar
    0
    kingdom created

    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&lt;IClock&gt;();
    
    protected IGuidGenerator GuidGenerator => LazyServiceProvider.LazyGetService&lt;IGuidGenerator&gt;(SimpleGuidGenerator.Instance);
    
    protected ILoggerFactory LoggerFactory => LazyServiceProvider.LazyGetRequiredService&lt;ILoggerFactory&gt;();
    
    protected ICurrentTenant CurrentTenant => LazyServiceProvider.LazyGetRequiredService&lt;ICurrentTenant&gt;();
    
    protected IAsyncQueryableExecuter AsyncExecuter => LazyServiceProvider.LazyGetRequiredService&lt;IAsyncQueryableExecuter&gt;();
    
    protected ILogger Logger => LazyServiceProvider.LazyGetService&lt;ILogger&gt;(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!

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Normally, the IGuidGenerator service will always be resolved. Does your application not resolve it?

    Thanks

  • User Avatar
    0
    kingdom created

    Hi there, Thanks for your reply! Let me clarify my confusion in detail: I confirm that IGuidGenerator is resolved correctly in the application (no resolution failures). My core question is about the default implementation binding in ABP’s DomainService/ApplicationService:The base classes (e.g., DomainService) have a protected property:

    protected IGuidGenerator GuidGenerator => LazyServiceProvider.LazyGetService<IGuidGenerator>(SimpleGuidGenerator.Instance);
    

    This means if IGuidGenerator is not explicitly registered, it falls back to SimpleGuidGenerator.Instance (which just wraps Guid.NewGuid()). Is this design expected and reasonable in ABP?

    To replace the default with SequentialGuidGenerator, I’m considering registering it via DI:

    context.Services.AddSingleton<IGuidGenerator, SequentialGuidGenerator>();
    

    Could you confirm if this is the ABP-idiomatic way to override the default implementation globally? Will this registration correctly replace the fallback SimpleGuidGenerator in DomainService/ApplicationService (i.e., make LazyGetService resolve SequentialGuidGenerator instead of the fallback)?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    The design here is that we will try to resolve IGuidGenerator from the dependency injection container, and if not found, we will use SimpleGuidGenerator.Instance.

    LazyServiceProvider.LazyGetService<IGuidGenerator>(SimpleGuidGenerator.Instance);

    Normal applications will always find it in the container, which is SequentialGuidGenerator if your module depended on AbpGuidsModule.

    Thanks.

  • User Avatar
    0
    roberto.fiocchi created

    Hi maliming, I asked myself the same question too.

    In the solution (MVC or Blazor with SQL) created with Abp Studio, I don't see any dependencies with AbpGuidsModule. Example [DependsOn(typeof(AbpGuidsModule))]

    Even adding entities with GUID IDs with Abp Suite doesn't add any dependencies to AbpGuidsModule.

    And the guide doesn't mention adding this dependency,but it says that SequentialGuidGenerator is the default. https://abp.io/docs/latest/framework/infrastructure/guid-generation#iguidgenerator

    Is the dependency recorded in a basic ABP module?

    Thansk

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Many modules will depend on the AbpGuidsModule

    It is a very basic module that is everywhere.

  • User Avatar
    0
    kingdom created

    I searched the entire solution for the keyword "AbpGuidsModule" and found that no module explicitly depends on AbpGuidsModule — it is likely that other built-in modules have a transitive dependency on it. I verified this through code testing:

    var actualGenerator = LazyServiceProvider.LazyGetService<IGuidGenerator>();
    Console.WriteLine($"GUID generator:{actualGenerator.GetType().FullName}");
    
    var guid = GuidGenerator.Create();
    Console.WriteLine($" GUID:{guid}");
    

    The test result confirmed that the generator in use is SequentialGuidGenerator, and the issue has been resolved.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Great 👍

Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.1.0-preview. Updated on December 08, 2025, 06:10
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.