Hi,
I checked our Hangfire module source code and also went through the Hangfire.SqlServer source code itself. There's no connection leak on either side — all connections are properly released with try-finally blocks, and the connection pool is handled by ADO.NET as expected.
ABP also doesn't have any hidden background polling that would create connections on its own. Things like SecurityStampValidator and MultiTenantConnectionStringResolver only run during HTTP requests, not on timers.
So the socket growth you're seeing is most likely not coming from ABP or Hangfire itself. Here are a few things worth checking:
1. Check your own code for connection leaks
Look for any place where you manually create SqlConnection, HttpClient, or other disposable objects without wrapping them in using. This is the most common cause of socket growth. For example:
// Bad - connection never disposed
var conn = new SqlConnection(connString);
conn.Open();
conn.Execute("...");
// Good
using var conn = new SqlConnection(connString);
conn.Open();
conn.Execute("...");
Also check if you're creating HttpClient instances per request instead of reusing them — each new HttpClient opens a new socket.
2. Azure SNAT port exhaustion
This is a very common issue on Azure App Service. When your app makes many short-lived outbound connections (to SQL, Redis, blob storage, etc.), Azure's SNAT ports can get exhausted, which causes exactly the symptoms you described. You can check this in Azure Portal → your App Service → Diagnose and Solve Problems → search for "SNAT".
More info: https://learn.microsoft.com/en-us/azure/app-service/troubleshoot-intermittent-outbound-connection-errors
3. Monitor what's actually using the sockets
You can use dotnet-counters to see what's happening:
dotnet-counters monitor --process-id <PID> --counters "Microsoft.Data.SqlClient.EventSource,System.Net.Sockets,System.Net.Http"
This will show you SQL connection pool stats, socket counts, and HTTP connection counts separately, so you can tell which component is actually leaking.
4. Reduce Hangfire connection usage
Even though Hangfire isn't leaking, you can reduce its connection throughput:
services.AddHangfire(config =>
config.UseSqlServerStorage(connectionString, new SqlServerStorageOptions
{
QueuePollInterval = TimeSpan.FromSeconds(30)
}));
services.AddHangfireServer(options =>
{
options.WorkerCount = 5;
});
Thanks
hi
We will release it within three days.
Thanks.
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:
This is a different production environment from the one we tested earlier (which showed 682ms), right? How many production environments do you have?
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?
Did you deploy all 4 files we provided to this environment? Specifically:
BulkPermissionStore.cs (the updated version with IsGrantedAsync override)PermissionGrantBulkCacheItem.csPermissionGrantBulkCacheItemInvalidator.csOptimizedPermissionChecker.cs ← this one is criticalThe 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?
How many microservices are running in this environment? Is it the same architecture as the other production?
What are the server specs (CPU/RAM) for this environment compared to your other production and local?
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
Hi,
This is a known issue — static CSS files like global-styles.css can't resolve PathBase because they have no server-side context. Neither root-absolute (/images/...) nor relative (images/...) paths work reliably across all bundling modes when hosted under a sub-path.
The workaround is to move these CSS variable definitions from the static file to a server-rendered Layout Hook, where Url.Content("~/...") properly respects PathBase.
Here's how:
1. Create a ViewComponent:
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
public class PathBaseStyleViewComponent : AbpViewComponent
{
public IViewComponentResult Invoke()
{
return View("~/Views/Shared/Components/PathBaseStyle/Default.cshtml");
}
}
2. Create the Razor view (Views/Shared/Components/PathBaseStyle/Default.cshtml):
<style>
:root {
--lpx-logo: url('@Url.Content("~/images/logo/leptonx/icon.svg")');
--lpx-logo-icon: url('@Url.Content("~/images/logo/leptonx/icon.svg")');
--lpx-theme-light-bg: url('@Url.Content("~/LeptonX/images/login-pages/login-bg-img-light.svg")');
--lpx-theme-dim-bg: url('@Url.Content("~/LeptonX/images/login-pages/login-bg-img-dim.svg")');
--lpx-theme-dark-bg: url('@Url.Content("~/LeptonX/images/login-pages/login-bg-img-dark.svg")');
}
</style>
3. Register the hook in your module:
Configure<AbpLayoutHookOptions>(options =>
{
options.Add(LayoutHooks.Head.Last, typeof(PathBaseStyleViewComponent));
});
4. Remove the CSS variable definitions from global-styles.css (the --lpx-logo, --lpx-logo-icon, and --lpx-theme-*-bg declarations). Keep the file if you have other custom styles in it.
With this approach, Url.Content("~/...") generates the correct path (e.g. /server/images/logo/leptonx/icon.svg) regardless of your PathBase configuration.
We're also looking into updating the LeptonX layouts to handle this internally so it works out of the box in future versions.
Thanks
Hi,
The error UNABLE_TO_VERIFY_LEAF_SIGNATURE is a Node.js SSL/TLS certificate chain verification error. This is not related to ABP or OpenIddict authentication — it means Node.js cannot verify the SSL certificate of your backend server during SSR requests.
To help confirm the root cause, could you provide some details:
NODE_TLS_REJECT_UNAUTHORIZED=0 before starting your SSR server make the error go away? (This is only for testing, not a production solution.)Thanks
Hi
replaceableComponents.add() is still working in v10, the API hasn't changed.
Since you're jumping from v8 to v10, there's a good chance the issue is related to the Angular 19 standalone migration rather than the replacement mechanism itself.
Could you share your app.config.ts, full app.component.ts, and one of your custom components (e.g. BreadcrumbComponent)? Also check if there are any errors in the browser console.
I'll try to reproduce the issue on my end once I see your setup.
Thanks
Alright, if you run into any other issues, just let me know.
Thanks.
Thank you. We will review your new question as soon as possible. 👍