Open Closed

Configuring Abp to have separate Application (Abp) and ETL (Abp+Hangfire) servers #9653


User avatar
0
roberto.fiocchi created

I created the Blazor WASM (Abp Commercial v.8.3.2) solution with Abp Studio, I use Hangfire to manage my ETL workflow.

The workflows must run on a single server (ETL Server - Abp with Hangfire) and must have the dashboard available.

The API endpoints, however, will be distributed across two servers (Application Servers - Only API), without Redis, which will run behind a load balancer. The Application Servers are intended for use with the Blazor WASM frontend.

I tried creating a configuration that enables and disables Hangfire via application settings, but I can't disable Hangfire on the application servers. Furthermore, I can't force the ABP background workers/jobs to run only on the ETL Server (Abp with Hangifire).

I need help and explanations on how to implement this configuration.

I'm attaching an example image of the final infrastructure.

Thanks


22 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent

    To achieve your desired infrastructure—where only the ETL server runs Hangfire and background jobs, and the API servers do not—you need to:

    1. Disable Hangfire and Background Job Execution on API Servers
    2. Enable Hangfire and Background Job Execution only on the ETL Server
    3. Ensure all jobs are queued in a shared database, so only the ETL server processes them
    4. Expose the Hangfire Dashboard only on the ETL server

    Step-by-Step Solution

    1. Shared Database for Background Jobs

    • Configure all your servers (API and ETL) to use the same database for background jobs (Hangfire/ABP).
    • This ensures jobs enqueued from any API server are visible to the ETL server.

    2. Disable Background Job Execution on API Servers

    In your API servers' appsettings.json or environment-specific settings, add:

    "AbpBackgroundJobs": {
      "IsJobExecutionEnabled": false
    }
    

    Or, in your module configuration:

    Configure<AbpBackgroundJobOptions>(options =>
    {
        options.IsJobExecutionEnabled = false;
    });
    

    Do NOT add or configure Hangfire server on the API servers:

    • Do not call context.Services.AddHangfireServer() on API servers.
    • Do not call app.UseAbpHangfireDashboard() on API servers.

    3. Enable Hangfire and Background Job Execution on ETL Server

    On the ETL server, enable Hangfire and background job execution:

    Configure<AbpBackgroundJobOptions>(options =>
    {
        options.IsJobExecutionEnabled = true;
    });
    context.Services.AddHangfire(config =>
    {
        config.UseSqlServerStorage(Configuration.GetConnectionString("Default"));
    });
    context.Services.AddHangfireServer();
    

    And in your OnApplicationInitialization:

    app.UseAbpHangfireDashboard("/hangfire");
    

    4. Environment-based Configuration

    Use environment variables or separate appsettings.{Environment}.json files to control which servers enable Hangfire/background jobs.

    Example:

    • On API servers: IsJobExecutionEnabled = false, no Hangfire server.
    • On ETL server: IsJobExecutionEnabled = true, Hangfire server enabled.

    5. Hangfire Dashboard

    • Only expose the Hangfire dashboard on the ETL server.
    • Secure it as needed (e.g., with authentication).

    Summary

    • API servers: Only enqueue jobs, do not process them.
    • ETL server: Processes jobs and hosts the Hangfire dashboard.
    • All use the same database for job storage.

    Sources


    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
    roberto.fiocchi created

    These examples replicate the ABP solution, I need to be able to use a single ABP solution and control the features based on the deployment (application settings) or publishing profile.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you try setting IsJobExecutionEnabled to true in one app and disabling it in other apps?

    Thanks.

    https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/AbpBackgroundJobOptions.cs#L15

  • User Avatar
    0
    roberto.fiocchi created

    But how do I register Hangifire only in the version to be released on ETL Server?

    I tried creating a JobManagerModule that derives from AbpModule in which I try to register Hangfire based on the app settings, but it seems like it always needs to be registered in the application servers as well.

    Example of my code:

    Thanks

    P.S. I sent you the solution.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    I will check your project.

    Thanks.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you try this?

    Configure<AbpBackgroundWorkerOptions>(options =>

    {
    
        options.IsEnabled = false;

    });


    
    Configure<AbpBackgroundJobOptions>(options =>

    {
    
        options.IsJobExecutionEnabled = false;
    });
    

    BTW, Hangfire supports multiple instances and automatically coordinates the execution of background jobs.

  • User Avatar
    0
    roberto.fiocchi created

    I will try, however my first problem is that I can't use the application settings to register Hangfire or not.

    Thanks

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Once you start using the ABP Hangfire modules, you have to configure them by default.

    But you can disable it.

    Thanks.

  • User Avatar
    0
    roberto.fiocchi created

    Sorry, I don't have time to test the proposed solution yet. Could you check if it works in the project already shared? If not, I'll do it tomorrow. In the meantime, I'll keep the ticket open.

    Thanks

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Ok, I will let the question remain open.

    Thanks.

  • User Avatar
    0
    roberto.fiocchi created

    I tried, but when I disable it from appsettings I get this error:

    Volo.Abp.AbpInitializationException: An error occurred during the initialize Volo.Abp.Modularity.OnPreApplicationInitializationModuleLifecycleContributor phase of the module Volo.Abp.BackgroundWorkers.Hangfire.AbpBackgroundWorkersHangfireModule, Volo.Abp.BackgroundWorkers.Hangfire, Version=8.3.2.0, Culture=neutral, PublicKeyToken=null: An exception was thrown while activating ?:Volo.Abp.Hangfire.AbpHangfireBackgroundJobServer -> ?:Hangfire.JobStorage.. See the inner exception for details. ---> Autofac.Core.DependencyResolutionException: An exception was thrown while activating ?:Volo.Abp.Hangfire.AbpHangfireBackgroundJobServer -> ?:Hangfire.JobStorage. ---> System.InvalidOperationException: Current JobStorage instance has not been initialized yet. You must set it before using Hangfire Client or Server API. For .NET Core applications please call the IServiceCollection.AddHangfire extension method from Hangfire.NetCore or Hangfire.AspNetCore package depending on your application type when configuring the services and ensure service-based APIs are used instead of static ones, like IBackgroundJobClient instead of BackgroundJob and IRecurringJobManager instead of RecurringJob. at Hangfire.JobStorage.get_Current() in C:\projects\hangfire-525\src\Hangfire.Core\JobStorage.cs:line 42

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    I tried, but when I disable it from appsettings I get this error:

    You should add Hangfire configuration code, but disable it with the abp options.

    context.Services.AddHangfire(config =>
    {
      config.UseSqlServerStorage(configuration.GetConnectionString("Default"));
    });
    

  • User Avatar
    0
    roberto.fiocchi created

    I did it, but it's not clear to me why it's needed since the jobs are not initialized and the worker I made to delete the logs is similar to ExpiredAuditLogDeleterWorker so it shouldn't depend on the presence or absence of HangFire. Can you explain it to me?

    Finally, I always see this call in the logs. I thought it was related to the ABP workers, but it doesn't seem to be the case since they should all be down now. Can you tell me what's causing it?

    2025-08-12T10:22:32.9921082+02:00 [INF] -
    (Microsoft.EntityFrameworkCore.Database.Command)
    Executed DbCommand ("4"ms) [Parameters=["@__p_0='0', @__p_1='1'"], CommandType='Text', CommandTimeout='30']"\r\n""SELECT [a].[Id], [a].[ConcurrencyStamp], [a].[EntityVersion], [a].[ExtraProperties], [a].[IsDefault], [a].[IsPublic], [a].[IsStatic], [a].[Name], [a].[NormalizedName], [a].[TenantId]\r\nFROM [AbpRoles] AS [a]\r\nWHERE [a].[TenantId] IS NULL\r\nORDER BY [a].[Id]\r\nOFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY"
    2025-08-12T10:22:32.9936939+02:00 [INF] -
    (Microsoft.EntityFrameworkCore.Update)
    Saved 2 entities to in-memory store.
    2025-08-12T10:22:42.9977294+02:00 [INF] -
    (Microsoft.EntityFrameworkCore.Database.Command)
    Executed DbCommand ("4"ms) [Parameters=["@__p_0='0', @__p_1='1'"], CommandType='Text', CommandTimeout='30']"\r\n""SELECT [a].[Id], [a].[ConcurrencyStamp], [a].[EntityVersion], [a].[ExtraProperties], [a].[IsDefault], [a].[IsPublic], [a].[IsStatic], [a].[Name], [a].[NormalizedName], [a].[TenantId]\r\nFROM [AbpRoles] AS [a]\r\nWHERE [a].[TenantId] IS NULL\r\nORDER BY [a].[Id]\r\nOFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY"
    2025-08-12T10:22:42.9995277+02:00 [INF] -
    (Microsoft.EntityFrameworkCore.Update)
    Saved 2 entities to in-memory store.
    

    Thanks

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Hangfire requires you to set up a valid storage so that you can add new jobs to it, even if they aren't executed in the current app.

  • User Avatar
    0
    roberto.fiocchi created

    Ok, and for my second question?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Saved 2 entities to in-memory store.

    This log only outputs if you are using Microsoft.EntityFrameworkCore.InMemory

  • User Avatar
    0
    roberto.fiocchi created

    [maliming] said:

    Saved 2 entities to in-memory store.

    This log only outputs if you are using Microsoft.EntityFrameworkCore.InMemory

    But who generates them since I have deactivated all workers and jobs?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi

    Maybe the DB call was not invoked by the background job/worker.

  • User Avatar
    0
    roberto.fiocchi created

    I don't use InMemory storage in my code, and the query looks like it's an ABP (Roles) module. It runs every 10 seconds.

    I've been asked to not have Workers running in the application servers and only have them in the ETL Server. Can you help me figure out which one it is so I can block it if possible or open an issue about it?

    Thanks

    P.s. You can use the repo shared with you for debug and test.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Try to disable/remove all HealthCheck from your project.

    Keyword: HealthCheck

    private void ConfigureHealthChecks(ServiceConfigurationContext context)
    {
        context.Services.AddMyProjectNameHealthChecks();
    }
    
  • User Avatar
    0
    roberto.fiocchi created

    Yes it was HealthCheck calling IdentityRoleRepository.GetListAsync

    I'm reporting a small problem with IdentityRole Repository (and maybe others too) The interface contains includeDetails = false

    But in the implementation, it's True.

    If the repository is injected with the interface, False wins. If it's injected with the class, True wins.

    I recommend that you align your implementation code with the defaults in the interface.

    Thanks!

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Thanks. I will fix it,

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.0.0-preview. Updated on September 04, 2025, 08:36