5 helpful tips to use hangfire for background scheduling in better way
Published: 2024-02-08 10:50:23


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3dyyhrf4384412i6kral.png)[Hangfire](https://www.hangfire.io/) is an easy way to perform background processing in .NET and .NET Core applications. No Windows Service or separate process required. If you have to deal with scheduled tasks like sending emails, taking recurring payments or notifying your customer about anything important, you must have heared of this awesome tool for sure.

[Hangfire](https://www.hangfire.io/) is very easy to configure and use. [Hangfire Documentation](https://docs.hangfire.io/en/latest/) reduces your learninig curve and you should be able to write your first job that does something meaniningful in a matter of hours. Once you start using [Hangfire](https://www.hangfire.io/) in production, you start realizing so many things and you start tweaking configuration and adjust your jobs to make it as per the best of your understanding.

So, in this article, we are going to share our experience with [Hangfire](https://www.hangfire.io/) and how we learned and adjusted our development and configuration of [Hangfire](https://www.hangfire.io/) to make it work for us in the best way. Let's get started with it.

1. Hangfire Console
[Hangfire Console](https://github.com/pieceofsummer/Hangfire.Console) is an additional tool that will allow you to write logs that are visible right into your [Hangfire](https://www.hangfire.io/) Dashboard job exeuction history page. Here is how you can quickly setup [Hangfire Console](https://github.com/pieceofsummer/Hangfire.Console):

- Add nuget package reference of [Hangfire Console](https://github.com/pieceofsummer/Hangfire.Console)

`  install-package hangfire.console`

- In the owin startup where you configured your hangfire, add following line:

`GlobalConfiguration.Configuration.UseConsole();`

- On top of your job cs file, add a using statement:

`using Hangfire.Console;`

- Write logs into Hangfire Job History pages by using its Console.WriteLine() method. For example:

`Console.WriteLine("Job started");`

If you are thoughtfully adding logs for warnings, informations, debugging or errors using Hangfire Console, it can be life saver to quickly track down your production issues.

**2. Handling Exceptions**

[Hangfire](https://www.hangfire.io/) comes with good default exception handling. If any job is failed, state of the job becomes Failed and detailed logs are available in the job history page. Due to default configuration, any failed job will automatically schedule for retry.

Now, consider a job that is sending out email to list of customers based on some business specific condition. At the time of execution of the job, 10 emails are expected to be sent but while sending 5th email, job fails because of smpt send timed out. The job will automatically retry and all emails will be attempted to send again. Obviously, we need to mainintain outgoing email sent log in database and make sure emails are not duplicated but if your customer base is big, this is again unproductive overhead to your system. In our case, our client was not interested into maintaining such table.

In order to resolve this we are handling exception for each send email and logging success or failure in the console. Other than that we configured hangfire to never retry failed jobs by setting following configuration:

`GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 0 });`

This will ensure even if the job fails, none of the jobs will be automatically executed.

For more information on dealing with exceptions, you can read Hangfire - [Dealing with exceptions](https://docs.hangfire.io/en/latest/background-processing/dealing-with-exceptions.html).

**3. Timezones**

When you are writing [Hangfire](https://www.hangfire.io/) jobs and schedule to run hourly or daily or any other recurrence, timezone matters the most in many cases. By default [Hangfire](https://www.hangfire.io/) uses UTC time. That means when you do not specify timezone information, its considered as UTC. You can configure jobs to run at a time and also pass on TimezoneInfo to it so that you can configure timezone specific time. Here is an example:

`  RecurringJob.AddOrUpdate(() => Console.Write(), "15 18 * * *", TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"));`

**4. Run same job Multiple times**

If you have written a [Hangfire](https://www.hangfire.io/) job and you want it to run multiple times in a day (not hourly), you can do it by passing job name like this:

`  RecurringJob.AddOrUpdate("TransactionTrackingJob-Morning", () => trackingJob.Execute(null), Cron.Daily(6), TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"));                  RecurringJob.AddOrUpdate("TransactionTrackingJob-Evening", () => trackingJob.Execute(null), Cron.Daily(21), TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"));`

This will make the transaction tracking job run twice a day, first in the morning and second in the evening at 6am and 9pm respectively.

**5. Retaining Logging for more time**
By default, [Hangfire](https://www.hangfire.io/) retains job execution history for only 1 day and after 24 hours it automatically deletes the history from database. In order to extend the time, add a new attribute declaration in your project:

`public class ProlongExpirationTimeAttribute : JobFilterAttribute, IApplyStateFilter  {   public void OnStateApplied(ApplyStateContext filterContext, IWriteOnlyTransaction transaction)   {    filterContext.JobExpirationTimeout = TimeSpan.FromDays(7);//make 7 to number of days you want   }     public void OnStateUnapplied(ApplyStateContext context, IWriteOnlyTransaction transaction)   {    context.JobExpirationTimeout = TimeSpan.FromDays(7);//make 7 to number of days you want   }  }   
`

and then in owin startup where you have configured hangfire, add another line like this:

`GlobalJobFilters.Filters.Add(new ProlongExpirationTimeAttribute()); `