Open Closed

Slow response time for /api/abp/application-configuration during login #10565


User avatar
0
vkelwan created

We are experiencing significant delay during user login due to a slow response from the following API:

/api/abp/application-configuration?includeLocalizationResources=false

This API call is taking longer than expected and is impacting the overall login performance and user experience. Observed Behavior

  • The API call consistently takes longer than expected.
  • This results in delayed application loading after login.
  • The issue is reproducible across multiple attempts.

Expected Behavior

  • The API should respond within an acceptable time (ideally under 500 ms).
  • The login and application initialization process should be smooth and fast.

Attachments

Please find the relevant screenshots below demonstrating the issue:

Markdown supported.
Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)

71 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Great progress — 744ms locally is a solid improvement! Now let's find out exactly why production is still 3–4 seconds.

    Please enable full debug logging temporarily on production by updating appsettings.json:

    {
      "Logging": {
        "LogLevel": {
          "Default": "Debug"
        }
      }
    }
    

    Then make one request to /api/abp/application-configuration?includeLocalizationResources=false and send us the full log output. The key things we're looking for:

    • Does it say BulkPermissionStore: cache hit or cache miss in production?
    • What is the Request finished line's duration (in ms) for that endpoint? This tells us the server-side time vs. browser-measured time.
    • Any slow operations from Volo.Abp.PermissionManagement or Volo.Abp.Caching.

    Also a few quick questions about your production setup:

    1. How many microservices are in your solution, and how many of them define their own permissions?
    2. Is your production Redis in the same data center / availability zone as your application servers, or in a different location?
    3. Do you have multiple instances of the application-configuration service running behind a load balancer?

    These details will help us pinpoint whether the slowness is coming from Redis latency, permission definition loading across services, or something else entirely.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    vkelwan created

    Hello good morning

    this logging we need to do in only admin service right ?

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Yes, the admin service is the right one. Please enable the debug logging there and share the log output for a single request.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    vkelwan created

    Hello can we connect over google meet ?

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Sure, we can do that if needed. But before the meeting, could you first share the debug log output from the admin service? That way we can have concrete data to look at together.

    Please enable the debug logging in the admin service as mentioned above, make one request to /api/abp/application-configuration?includeLocalizationResources=false on the production server, and share the full log output liming.ma@volosoft.com.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    vkelwan created

    Hello this is log on hard refresh [05:01:40 DBG] Executing AbpApplicationConfigurationAppService.GetAsync()...

    [05:01:40 DBG] BulkPermissionStore: cache hit for U:0e3c4557-57fd-31b4-7781-3a1df656b05c.

    [05:01:40 DBG] BulkPermissionStore: cache hit for R:admin.

    [05:01:40 DBG] BulkPermissionStore: cache hit for C:Angular.

    [05:01:40 DBG] Executed AbpApplicationConfigurationAppService.GetAsync().

    [05:01:40 INF] Executing ObjectResult, writing value of type 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationConfigurationDto'.

    [05:01:40 INF] Executed action Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc) in 680.5212ms

    [05:01:40 INF] Executed endpoint 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc)'

    [05:01:40 INF] Request finished HTTP/1.1 GET http://adminserver/api/abp/application-configuration?includeLocalizationResources=false - 200 null application/json; charset=utf-8 682.3877ms

    [05:01:41 INF] Request starting HTTP/1.1 GET http://adminserver/api/abp/application-localization?cultureName=en-GB&onlyDynamics=false - null null

    [05:01:41 INF] CORS policy execution successful.

    [05:01:41 INF] Executing endpoint 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationLocalizationController.GetAsync (Volo.Abp.AspNetCore.Mvc)'

    [05:01:41 INF] Route matched with {area = "abp", action = "Get", controller = "AbpApplicationLocalization", page = ""}. Executing controller action with signature System.Threading.Tasks.Task`1[Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationLocalizationDto] GetAsync(Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationLocalizationRequestDto) on controller Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationLocalizationController (Volo.Abp.AspNetCore.Mvc).

    Can you please connect over a meeting? I want to clarify one thing.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Thanks for the logs! The server-side processing time is 682ms, and all three bulk cache lookups are hitting the cache (U, R, C). The optimizations are working well on the server side.

    The 996ms in the browser includes network latency between your browser and the production server, which is expected.

    Just to confirm — compared to the original 10+ seconds, does this feel like the issue is resolved for you now? Or is there still something you'd like us to look into further?

    You also mentioned you wanted to clarify something — what is it?

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    vkelwan created

    can we connect over google meet ?

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    What issues are you currently running into? Happy to help here.

    If there's any sensitive information you'd prefer not to share publicly, feel free to email me at liming.ma@volosoft.com.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Just to let you know, we've identified several performance bottlenecks in the framework when dealing with a large number of permissions. We'll be making enhancements in a future version to improve this out of the box.

    In the meantime, the workaround files we provided should keep things running smoothly for you.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    The enhanced PR: https://github.com/abpframework/abp/pull/25231

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    vkelwan created

    so does this we will ge in next abp deployment? so do i need to remove what 4 files we added that

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Yes, these optimizations will be included in the next ABP release (10.3). Once you upgrade to 10.3, you can remove all 4 files we provided.

    For now, please keep the patch files as they are — they're working well and giving you better performance than the framework changes alone (especially the bulk cache optimization for Redis).

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you create a new question for your new case?

    Thanks.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Thank you. We will review your new question as soon as possible. 👍

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    vkelwan created

    Hello This api in my other production taking 4 sec

    This is log of first login

    10:10:14LOG[04:38:41 DBG] BulkPermissionStore: cache miss for U:c90580c7-382d-de83-3b8a-3a1fd52c9d3c, loading from DB. 10:10:14LOG[04:38:41 DBG] BulkPermissionStore: cached 0 granted permissions for U:c90580c7-382d-de83-3b8a-3a1fd52c9d3c. 10:10:14LOG[04:38:41 DBG] BulkPermissionStore: cache miss for R:admin, loading from DB. 10:10:14LOG[04:38:42 DBG] BulkPermissionStore: cached 8389 granted permissions for R:admin. 10:10:14LOG[04:38:42 DBG] BulkPermissionStore: cache miss for C:Angular, loading from DB. 10:10:14LOG[04:38:42 DBG] BulkPermissionStore: cached 0 granted permissions for C:Angular. 10:10:14LOG[04:38:42 DBG] Executed AbpApplicationConfigurationAppService.GetAsync(). 10:10:14LOG[04:38:43 INF] Executing ObjectResult, writing value of type 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationConfigurationDto'. 10:10:14LOG[04:38:43 INF] Executed action Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc) in 3499.4922ms 10:10:14LOG[04:38:43 INF] Executed endpoint 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc)' 10:10:14LOG[04:38:43 INF] Request finished HTTP/1.1 GET http://adminserver/api/abp/application-configuration?includeLocalizationResources=false - 200 null application/json; charset=utf-8 3798.3348ms

    This is Log after login any page refresh

    10:10:15LOG[04:40:12 DBG] BulkPermissionStore: cache hit for U:c90580c7-382d-de83-3b8a-3a1fd52c9d3c. 10:10:15LOG[04:40:12 DBG] BulkPermissionStore: cache hit for R:admin. 10:10:15LOG[04:40:12 DBG] BulkPermissionStore: cache hit for C:Angular. 10:10:15LOG[04:40:12 DBG] Executed AbpApplicationConfigurationAppService.GetAsync(). 10:10:15LOG[04:40:12 INF] Executing ObjectResult, writing value of type 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationConfigurationDto'. 10:10:15LOG[04:40:12 INF] Executed action Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc) in 1954.0202ms 10:10:15LOG[04:40:12 INF] Executed endpoint 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc)' 10:10:15LOG[04:40:12 INF] Request finished HTTP/1.1 GET http://adminserver/api/abp/application-configuration?includeLocalizationResources=false - 200 null application/json; charset=utf-8 1957.8207ms 10:10:15LOG[04:40:12 INF] Request starting HTTP/1.1 GET http://adminserver/api/abp/application-localization?cultureName=en-GB&onlyDynamics=false - null null

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi

    I can see BulkPermissionStore is working — cache hits are showing correctly. But the warm cache time (1954ms) is still high, which tells me there's more we can optimize.

    A few questions about this environment:

    1. This is a different production environment from the one we tested earlier (which showed 682ms), right? How many production environments do you have?

    2. I see 8389 granted permissions for the R:admin role — that's significantly more than your other environment. Is this expected? Do different environments have different permission configurations?

    3. Did you deploy all 4 files we provided to this environment? Specifically:

      • BulkPermissionStore.cs (the updated version with IsGrantedAsync override)
      • PermissionGrantBulkCacheItem.cs
      • PermissionGrantBulkCacheItemInvalidator.cs
      • OptimizedPermissionChecker.cs ← this one is critical

      The OptimizedPermissionChecker.cs handles the application-layer optimization. Without it, even with BulkPermissionStore working, 8389 permissions will still cause ~2 seconds of processing overhead. Could you check if this file is included and properly registered?

    4. How many microservices are running in this environment? Is it the same architecture as the other production?

    5. What are the server specs (CPU/RAM) for this environment compared to your other production and local?

    6. Could you also share the warm cache log from your first production environment (the one that showed 682ms) for comparison? I want to confirm that environment has all 4 files working.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    vkelwan created

    Hello This is a different production environment from the one we tested earlier (which showed 682ms), right? How many production environments do you have?

    we have 3 producation

    I see 8389 granted permissions for the R:admin role — that's significantly more than your other environment. Is this expected? Do different environments have different permission configurations?

    not cause of this producation has less module

    Did you deploy all 4 files we provided to this environment? Specifically: yes all 4 files shared

    How many microservices are running in this environment? Is it the same architecture as the other production? same architecture but in this we only used hotel module

    What are the server specs (CPU/RAM) for this environment compared to your other production and local?

    128 GB RAM, 24 Cores (48 Threads) this is of that producation in which taking

    and both severs in netherlands

    Could you also share the warm cache log from your first production environment (the one that showed 682ms) for comparison? I want to confirm that environment has all 4 files working.

    This First time login removing all cookies and all [09:53:14 DBG] BulkPermissionStore: cache miss for U:0162719b-2c7b-adb3-a629-3a1dfef2a46e, loading from DB.

    [09:53:14 DBG] BulkPermissionStore: cached 181 granted permissions for U:0162719b-2c7b-adb3-a629-3a1dfef2a46e.

    [09:53:14 DBG] BulkPermissionStore: cache miss for R:admin, loading from DB.

    [09:53:14 DBG] BulkPermissionStore: cached 4410 granted permissions for R:admin.

    [09:53:14 DBG] BulkPermissionStore: cache miss for C:Angular, loading from DB.

    [09:53:14 DBG] BulkPermissionStore: cached 0 granted permissions for C:Angular.

    [09:53:15 DBG] Executed AbpApplicationConfigurationAppService.GetAsync().

    [09:53:15 INF] Executing ObjectResult, writing value of type 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationConfigurationDto'.

    [09:53:15 INF] Executed action Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc) in 1200.108ms

    THis is after login on page refresh [09:54:27 DBG] Executing AbpApplicationConfigurationAppService.GetAsync()...

    [09:54:28 DBG] BulkPermissionStore: cache hit for U:0162719b-2c7b-adb3-a629-3a1dfef2a46e.

    [09:54:28 DBG] BulkPermissionStore: cache hit for R:admin.

    [09:54:28 DBG] BulkPermissionStore: cache hit for C:Angular.

    [09:54:28 DBG] Executed AbpApplicationConfigurationAppService.GetAsync().

    [09:54:28 INF] Executing ObjectResult, writing value of type 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationConfigurationDto'.

    [09:54:28 INF] Executed action Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc) in 829.4288ms

    [09:54:28 INF] Executed endpoint 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc)'

    [09:54:28 INF] Request finished HTTP/1.1 GET http://adminserver/api/abp/application-configuration?includeLocalizationResources=false - 200 null application/json; charset=utf-8 833.1524ms

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    vkelwan created

    and one thing i have shared picture of role permission in that not having 4000 permission then where this all 4000 permission is getting can we connect over meet call ?

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Thanks for the detailed logs and screenshots! Let me address everything.

    About the warm cache performance (1954ms / 829ms)

    Even though BulkPermissionStore is working well (all cache hits), there's still a bottleneck in GetAuthConfigAsync — it calls GetOrNullAsync for every single permission in a loop. With 4410 permissions that's 4410 async calls, with 8389 it's 8389 async calls. This is why the time is proportional to permission count.

    We have a 5th patch file that fixes this. Please add OptimizedAppConfigurationAppService.cs to your project alongside the other 4 files:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.Extensions.Options;
    using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
    using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending;
    using Volo.Abp.Authorization;
    using Volo.Abp.Authorization.Permissions;
    using Volo.Abp.DependencyInjection;
    using Volo.Abp.Features;
    using Volo.Abp.Localization;
    using Volo.Abp.MultiTenancy;
    using Volo.Abp.Settings;
    using Volo.Abp.Timing;
    using Volo.Abp.Users;
    
    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(IAbpApplicationConfigurationAppService))]
    public class OptimizedAppConfigurationAppService : AbpApplicationConfigurationAppService
    {
        public OptimizedAppConfigurationAppService(
            IOptions<AbpLocalizationOptions> localizationOptions,
            IOptions<AbpMultiTenancyOptions> multiTenancyOptions,
            IServiceProvider serviceProvider,
            IAbpAuthorizationPolicyProvider abpAuthorizationPolicyProvider,
            IPermissionDefinitionManager permissionDefinitionManager,
            DefaultAuthorizationPolicyProvider defaultAuthorizationPolicyProvider,
            IPermissionChecker permissionChecker,
            IAuthorizationService authorizationService,
            ICurrentUser currentUser,
            ISettingProvider settingProvider,
            ISettingDefinitionManager settingDefinitionManager,
            IFeatureDefinitionManager featureDefinitionManager,
            ILanguageProvider languageProvider,
            ITimezoneProvider timezoneProvider,
            IOptions<AbpClockOptions> abpClockOptions,
            ICachedObjectExtensionsDtoService cachedObjectExtensionsDtoService,
            IOptions<AbpApplicationConfigurationOptions> options)
            : base(localizationOptions, multiTenancyOptions, serviceProvider,
                abpAuthorizationPolicyProvider, permissionDefinitionManager,
                defaultAuthorizationPolicyProvider, permissionChecker,
                authorizationService, currentUser, settingProvider,
                settingDefinitionManager, featureDefinitionManager,
                languageProvider, timezoneProvider, abpClockOptions,
                cachedObjectExtensionsDtoService, options)
        {
        }
    
        protected override async Task<ApplicationAuthConfigurationDto> GetAuthConfigAsync()
        {
            var authConfig = new ApplicationAuthConfigurationDto();
    
            var abpAuthorizationPolicyProvider = LazyServiceProvider
                .LazyGetRequiredService<IAbpAuthorizationPolicyProvider>();
            var permissionDefinitionManager = LazyServiceProvider
                .LazyGetRequiredService<IPermissionDefinitionManager>();
            var defaultAuthorizationPolicyProvider = LazyServiceProvider
                .LazyGetRequiredService<DefaultAuthorizationPolicyProvider>();
            var permissionChecker = LazyServiceProvider
                .LazyGetRequiredService<IPermissionChecker>();
            var authorizationService = LazyServiceProvider
                .LazyGetRequiredService<IAuthorizationService>();
    
            var policyNames = await abpAuthorizationPolicyProvider.GetPoliciesNamesAsync();
            var abpPolicyNames = new List<string>();
            var otherPolicyNames = new List<string>();
    
            var permissionNameSet = new HashSet<string>(
                (await permissionDefinitionManager.GetPermissionsAsync()).Select(p => p.Name),
                StringComparer.Ordinal);
    
            foreach (var policyName in policyNames)
            {
                if (await defaultAuthorizationPolicyProvider.GetPolicyAsync(policyName) == null &&
                    permissionNameSet.Contains(policyName))
                {
                    abpPolicyNames.Add(policyName);
                }
                else
                {
                    otherPolicyNames.Add(policyName);
                }
            }
    
            foreach (var policyName in otherPolicyNames)
            {
                if (await authorizationService.IsGrantedAsync(policyName))
                {
                    authConfig.GrantedPolicies[policyName] = true;
                }
            }
    
            var result = await permissionChecker.IsGrantedAsync(abpPolicyNames.ToArray());
            foreach (var item in result.Result)
            {
                if (item.Value == PermissionGrantResult.Granted)
                {
                    authConfig.GrantedPolicies[item.Key] = true;
                }
            }
    
            return authConfig;
        }
    }
    

    Note: The constructor parameters must match your ABP version (9.2.0). If you get a compile error about constructor parameters, please let me know and I'll adjust.

    About the permission count (UI shows ~1800 but cache shows 4410/8389)

    The permission count in the cache comes from the AbpPermissionGrants database table — it shows how many permissions are granted, not how many are defined. In your screenshot I can see "Grant all permissions" is checked, so all defined permissions get granted.

    The UI dialog shows permissions from currently registered modules. But the database may contain grants from previously installed modules that were later removed. These orphaned grants are harmless but they increase the cache size. You can verify by running this SQL on both databases:

    SELECT COUNT(*) FROM AbpPermissionGrants WHERE ProviderName = 'R' AND ProviderKey = 'admin';
    

    About a meeting

    I understand the desire for a call, but the bottleneck here is something we can only diagnose through logs and data — a meeting wouldn't give us more visibility than what the debug logs already show. Each round of logs has helped us identify and fix a specific layer of the problem. Please try deploying this 5th file and share the updated logs — I expect a significant improvement.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    vkelwan created

    Sorry but I want to understand why there is this much permission in the database and in the UI, not why.

    this is log of second environment in which call taking 4 sec. This permission in the tenant database This permission in host database

    I want to make the same permission as in the UI and know this difference also. Why is there so difference between host and tenant

    one more thing that why ui permisison count and databse not matching ?

    And regarding calls, why am I asking? Because on calls I can show you architecture. and all so in one moment we can solve this

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Let me explain what's happening with the permission counts.

    Why Host (8389) has more than Tenant (4317)

    This is expected in ABP multi-tenancy. Each permission definition has a MultiTenancySide flag — it can be Host, Tenant, or Both. When you click "Grant all permissions":

    • On the Host side: it grants all permissions marked as Host or Both
    • On the Tenant side: it grants all permissions marked as Tenant or Both

    Host typically has more permissions because some permissions are host-only (e.g., tenant management, edition management). So the difference between 8389 and 4317 is normal.

    Why the database has more than the UI shows (~1810)

    The permission management UI only shows currently defined permissions — permissions that your running microservices actively register. But the AbpPermissionGrants table stores all grants ever made, including grants for permissions that no longer exist (orphaned grants).

    This can happen when:

    • A module was installed, "Grant all" was clicked, then the module was later removed or replaced
    • Permission names were changed in a module update (old grants for old names remain)
    • A microservice was previously running and registered permissions, but is no longer active

    Important: Don't delete these records

    In a microservices architecture, the AbpPermissionGrants table might be shared across services. What looks like "orphaned" from the admin service UI might actually be permissions registered by other microservices that aren't visible in the current admin UI. Deleting them could break permission checks in those services.

    ABP safely ignores grants for undefined permissions at runtime, so they don't cause any functional issues.

    How to investigate

    You can run these queries to understand the data better. These are read-only queries, just for investigation:

    -- 1. How many grants per provider in this database?
    SELECT ProviderName, ProviderKey, COUNT(*) as GrantCount
    FROM AbpPermissionGrants
    GROUP BY ProviderName, ProviderKey
    ORDER BY GrantCount DESC;
    
    -- 2. Find permission names that are granted but might not be currently defined
    -- Export this list and compare with what you see in the UI
    SELECT DISTINCT Name
    FROM AbpPermissionGrants
    WHERE ProviderName = 'R' AND ProviderKey = 'admin'
    ORDER BY Name;
    
    -- 3. Check if there are duplicate grants (same permission granted multiple times)
    SELECT Name, COUNT(*) as Cnt
    FROM AbpPermissionGrants
    WHERE ProviderName = 'R' AND ProviderKey = 'admin'
    GROUP BY Name
    HAVING COUNT(*) > 1;
    

    Query #2 will give you the full list of granted permission names. You can compare this with the permissions shown in the UI to identify which ones are "extra". Most likely they belong to modules or services that were previously installed.

    About the 5th patch file

    Did you get a chance to deploy the OptimizedAppConfigurationAppService.cs file I shared earlier? That should help with the remaining performance issue. Please share the updated logs after deploying it.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    vkelwan created

    Hello i did 5th file but took too much time

    this server login logs 10:30:51 LOG [04:55:39 DBG] BulkPermissionStore: cache hit for U:8e19f3c2-3cca-01a5-c78a-3a1fd5abe6b6. 10:30:51 LOG [04:55:39 DBG] BulkPermissionStore: cache hit for R:admin. 10:30:51 LOG [04:55:39 DBG] BulkPermissionStore: cache hit for C:Angular. 10:30:51 LOG [04:55:39 DBG] Executed AbpApplicationConfigurationAppService.GetAsync(). 10:30:51 LOG [04:55:39 INF] Executing ObjectResult, writing value of type 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationConfigurationDto'. 10:30:51 LOG [04:55:39 INF] Executed action Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc) in 4423.175ms 10:30:51 LOG [04:55:39 INF] Executed endpoint 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc)' 10:30:51 LOG [04:55:39 INF] Request finished HTTP/1.1 GET http://adminserver/api/abp/application-configuration?includeLocalizationResources=false - 200 null application/json; charset=utf-8 4542.4664ms 10:30:51 LOG [04:55:41 INF] Request starting HTTP/1.1 GET http://adminserver/api/abp/application-localization?cultureName=en&onlyDynamics=false - null null

    and this is very random behavior on page refresh 0:46:35 LOG [05:13:51 DBG] BulkPermissionStore: cache hit for U:8e19f3c2-3cca-01a5-c78a-3a1fd5abe6b6. 10:46:35 LOG [05:13:51 DBG] BulkPermissionStore: cache hit for R:admin. 10:46:35 LOG [05:13:51 DBG] BulkPermissionStore: cache hit for C:Angular. 10:46:35 LOG [05:13:56 INF] Executing ObjectResult, writing value of type 'Volo.Abp.PermissionManagement.GetPermissionListResultDto'. 10:46:35 LOG [05:13:56 INF] Executed action Volo.Abp.PermissionManagement.PermissionsController.GetAsync (Volo.Abp.PermissionManagement.HttpApi) in 5119.4761ms 10:46:35 LOG [05:13:56 INF] Executed endpoint 'Volo.Abp.PermissionManagement.PermissionsController.GetAsync (Volo.Abp.PermissionManagement.HttpApi)' 10:46:35 LOG [05:13:56 INF] Request finished HTTP/1.1 GET http://adminserver/api/permission-management/permissions?providerName=R&providerKey=admin - 200 null application/json; charset=utf-8 5159.0171ms 10:46:35 LOG [05:13:57 DBG] Executing HealthCheck collector HostedService. 10:46:35 LOG [05:13:57 INF] Start processing HTTP request GET http://[::]/health-status 10:46:35 LOG [05:13:57 INF] Sending HTTP request GET http://[::]/health-status

    And this is all their query result in the tenant database.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Thanks for testing. The 3391ms is likely a one-time cold start after restarting the application — the permission definition cache needs to reload from the database on the first request.

    Could you please refresh the page once more and share the server log for that second request? We need to compare it with the previous 1954ms to see if the optimization is working.

    Also, I've updated the OptimizedAppConfigurationAppService.cs with timing logs for each step. Please replace the file with this new version — it will tell us exactly where the time is being spent:

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
    using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending;
    using Volo.Abp.Authorization;
    using Volo.Abp.Authorization.Permissions;
    using Volo.Abp.DependencyInjection;
    using Volo.Abp.Features;
    using Volo.Abp.Localization;
    using Volo.Abp.MultiTenancy;
    using Volo.Abp.Settings;
    using Volo.Abp.Timing;
    using Volo.Abp.Users;
    
    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(IAbpApplicationConfigurationAppService))]
    public class OptimizedAppConfigurationAppService : AbpApplicationConfigurationAppService
    {
        public OptimizedAppConfigurationAppService(
            IOptions<AbpLocalizationOptions> localizationOptions,
            IOptions<AbpMultiTenancyOptions> multiTenancyOptions,
            IServiceProvider serviceProvider,
            IAbpAuthorizationPolicyProvider abpAuthorizationPolicyProvider,
            IPermissionDefinitionManager permissionDefinitionManager,
            DefaultAuthorizationPolicyProvider defaultAuthorizationPolicyProvider,
            IPermissionChecker permissionChecker,
            IAuthorizationService authorizationService,
            ICurrentUser currentUser,
            ISettingProvider settingProvider,
            ISettingDefinitionManager settingDefinitionManager,
            IFeatureDefinitionManager featureDefinitionManager,
            ILanguageProvider languageProvider,
            ITimezoneProvider timezoneProvider,
            IOptions<AbpClockOptions> abpClockOptions,
            ICachedObjectExtensionsDtoService cachedObjectExtensionsDtoService,
            IOptions<AbpApplicationConfigurationOptions> options)
            : base(localizationOptions, multiTenancyOptions, serviceProvider,
                abpAuthorizationPolicyProvider, permissionDefinitionManager,
                defaultAuthorizationPolicyProvider, permissionChecker,
                authorizationService, currentUser, settingProvider,
                settingDefinitionManager, featureDefinitionManager,
                languageProvider, timezoneProvider, abpClockOptions,
                cachedObjectExtensionsDtoService, options)
        {
        }
    
        protected override async Task<ApplicationAuthConfigurationDto> GetAuthConfigAsync()
        {
            var sw = Stopwatch.StartNew();
    
            var authConfig = new ApplicationAuthConfigurationDto();
    
            var abpAuthorizationPolicyProvider = LazyServiceProvider
                .LazyGetRequiredService<IAbpAuthorizationPolicyProvider>();
            var permissionDefinitionManager = LazyServiceProvider
                .LazyGetRequiredService<IPermissionDefinitionManager>();
            var defaultAuthorizationPolicyProvider = LazyServiceProvider
                .LazyGetRequiredService<DefaultAuthorizationPolicyProvider>();
            var permissionChecker = LazyServiceProvider
                .LazyGetRequiredService<IPermissionChecker>();
            var authorizationService = LazyServiceProvider
                .LazyGetRequiredService<IAuthorizationService>();
    
            var policyNames = await abpAuthorizationPolicyProvider.GetPoliciesNamesAsync();
            var abpPolicyNames = new List<string>();
            var otherPolicyNames = new List<string>();
    
            var permissionNameSet = new HashSet<string>(
                (await permissionDefinitionManager.GetPermissionsAsync()).Select(p => p.Name),
                StringComparer.Ordinal);
    
            foreach (var policyName in policyNames)
            {
                if (await defaultAuthorizationPolicyProvider.GetPolicyAsync(policyName) == null &&
                    permissionNameSet.Contains(policyName))
                {
                    abpPolicyNames.Add(policyName);
                }
                else
                {
                    otherPolicyNames.Add(policyName);
                }
            }
    
            foreach (var policyName in otherPolicyNames)
            {
                if (await authorizationService.IsGrantedAsync(policyName))
                {
                    authConfig.GrantedPolicies[policyName] = true;
                }
            }
    
            var result = await permissionChecker.IsGrantedAsync(abpPolicyNames.ToArray());
            foreach (var item in result.Result)
            {
                if (item.Value == PermissionGrantResult.Granted)
                {
                    authConfig.GrantedPolicies[item.Key] = true;
                }
            }
    
            Logger.LogInformation("OptimizedAppConfig: GetAuthConfigAsync took {Elapsed}ms", sw.ElapsedMilliseconds);
            return authConfig;
        }
    
        protected override async Task<ApplicationFeatureConfigurationDto> GetFeaturesConfigAsync()
        {
            var sw = Stopwatch.StartNew();
            var result = await base.GetFeaturesConfigAsync();
            Logger.LogInformation("OptimizedAppConfig: GetFeaturesConfigAsync took {Elapsed}ms", sw.ElapsedMilliseconds);
            return result;
        }
    
        protected override async Task<ApplicationLocalizationConfigurationDto> GetLocalizationConfigAsync(
            ApplicationConfigurationRequestOptions options)
        {
            var sw = Stopwatch.StartNew();
            var result = await base.GetLocalizationConfigAsync(options);
            Logger.LogInformation("OptimizedAppConfig: GetLocalizationConfigAsync took {Elapsed}ms", sw.ElapsedMilliseconds);
            return result;
        }
    
        protected override async Task<TimingDto> GetTimingConfigAsync()
        {
            var sw = Stopwatch.StartNew();
            var result = await base.GetTimingConfigAsync();
            Logger.LogInformation("OptimizedAppConfig: GetTimingConfigAsync took {Elapsed}ms", sw.ElapsedMilliseconds);
            return result;
        }
    }
    

    After deploying, please make two requests (first login + one page refresh) and share the full server logs. We'll see something like:

    OptimizedAppConfig: GetAuthConfigAsync took XXms
    OptimizedAppConfig: GetFeaturesConfigAsync took XXms
    OptimizedAppConfig: GetLocalizationConfigAsync took XXms
    OptimizedAppConfig: GetTimingConfigAsync took XXms
    

    This will tell us exactly which part is slow.

    About the permission count in the database

    • Host (8389) vs Tenant (4317): This is expected. ABP permissions have a MultiTenancySide setting — some permissions are host-only (like tenant management). When you click "Grant all permissions" on the host side, it grants more permissions than on the tenant side. So the difference is normal.

    • Database (4317) vs UI (~1810): The AbpPermissionGrants table stores all grants ever made. The UI only shows permissions that are currently defined by your running microservices. The difference could be from:

      • Modules or microservices that were previously installed and had "Grant all" clicked, but were later removed
      • Microservices that registered permissions but are no longer connected to the admin service
      • Permission names that changed in module updates (old grants remain)

    These extra grants in the database are harmless — ABP ignores them at runtime. They don't affect functionality or security. I would not recommend deleting them, especially in a microservices setup where other services might still reference those permissions.

    To check if there are grants for permissions that no longer have a definition record:

    SELECT pg.Name
    FROM AbpPermissionGrants pg
    WHERE pg.ProviderName = 'R' AND pg.ProviderKey = 'admin'
    AND pg.Name NOT IN (SELECT Name FROM AbpPermissions)
    ORDER BY pg.Name;
    

    Note: ABP also keeps old permission definitions in the AbpPermissions table even after a module is removed, so this query might not find all the "extra" ones. The difference between the UI count and the database count is mostly due to how ABP accumulates data over time across all your microservices.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    vkelwan created

    Hello Here' logs

    10:59:26 LOG [05:28:58 DBG] Executing AbpApplicationConfigurationAppService.GetAsync()... 10:59:26 LOG [05:29:01 DBG] BulkPermissionStore: cache hit for U:8e19f3c2-3cca-01a5-c78a-3a1fd5abe6b6. 10:59:26 LOG [05:29:01 DBG] BulkPermissionStore: cache hit for R:admin. 10:59:27 LOG [05:29:01 DBG] BulkPermissionStore: cache hit for C:Angular. 10:59:27 LOG [05:29:01 INF] OptimizedAppConfig: GetAuthConfigAsync took 3474ms 10:59:27 LOG [05:29:02 INF] OptimizedAppConfig: GetFeaturesConfigAsync took 29ms 10:59:27 LOG [05:29:02 INF] OptimizedAppConfig: GetLocalizationConfigAsync took 0ms 10:59:27 LOG [05:29:02 INF] OptimizedAppConfig: GetTimingConfigAsync took 1ms 10:59:27 LOG [05:29:02 DBG] Executed AbpApplicationConfigurationAppService.GetAsync(). 10:59:27 LOG [05:29:02 INF] Executing ObjectResult, writing value of type 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationConfigurationDto'. 10:59:27 LOG [05:29:02 INF] Executed action Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc) in 3517.6511ms 10:59:27 LOG [05:29:02 INF] Executed endpoint 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc)' 10:59:27 LOG [05:29:02 INF] Request finished HTTP/1.1 GET http://adminserver/api/abp/application-configuration?includeLocalizationResources=false - 200 null application/json; charset=utf-8 3523.1263ms 10:59:27 LOG [05:29:02 INF] Request starting HTTP/1.1 GET http://adminserver/api/abp/application-localization?cultureName=en&onlyDynamics=false - null null

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
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.8.0-preview. Updated on September 16, 2026, 14:50
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.