We want to run a Batch job that runs hourly and updates the users to Inactive if they are logged in last 2 Hours but not 30 Minutes. The Code works fine when I run it manually and but i need to run this job every hour forever until we stop. I did some research and it looks like we need to write a cron expression in Dev console however this doesn't seems to be working, there are no users who got updated and when i see apex jobs, there are no batches processed. Wonder If I'm doing it wrong.

//Batch class

global class ScheduleInactiveUser Implements Schedulable,  Database.Batchable<sObject> {
  private DateTime LoggedInPast2Hours = System.now().addMinutes(-120);
  private DateTime LoggedInPast30Mins = System.now().addMinutes(-30);

  global void execute(SchedulableContext sc) {
    Database.executeBatch(this, 200); 

  global Database.QueryLocator start(Database.BatchableContext BC) {  
    string query = 'Select Id, LastLoginDate, IsActive, Name From User Where Profile_Name__c = \'Portal JIT User\' AND LastLoginDate >= :LoggedInPast2Hours AND LastLoginDate <=: LoggedInPast30Mins AND IsActive = TRUE';
    return Database.getQueryLocator(query);

  global void execute(Database.BatchableContext BC, List<sObject> scope) {
    List<User> UserList = (List<User>) scope;
    for(User c : UserList){
      c.IsActive = False;
    update UserList;
  global void finish(Database.BatchableContext BC) {

I'm running below code in Dev Console

System.schedule('Hourly Job to InActivate Portal Users', '0 0 * * * ?', new ScheduleInactiveUser());

I can see the scheduled job for next hour as well, but it just doesn't seems to be working. I wonder if the above CRON expression is correct?. Am I doing something wrong?

  • Are you getting values for the variables LoggedInPast2Hours and LoggedInPast30Mins in your Start function? Would you be able to set those variables in your Start function, before the query? It might not be storing across your Execute and Start transactions. Commented Mar 15, 2021 at 19:46

2 Answers 2


When your code is scheduled, the private properties you've defined are stored for later use. Therefore, they will never be updated, and only update users that met the criteria when the scheduler was initially scheduled. Move the variables to the start method:

global Database.QueryLocator start(Database.BatchableContext BC) {  
    DateTime LoggedInPast2Hours = System.now().addMinutes(-120);
    DateTime LoggedInPast30Mins = System.now().addMinutes(-30);
    return Database.getQueryLocator([Select Id, LastLoginDate, IsActive, Name From User Where Profile_Name__c = 'Portal JIT User' AND LastLoginDate >= :LoggedInPast2Hours AND LastLoginDate <=: LoggedInPast30Mins AND IsActive = TRUE]);

Note that you can, and should, use an inline query, instead. Do not use a dynamic query if you can help it.

Also, I kind of doubt this is exactly the sort of thing you want to do, as it basically forces the user to have to re-register every time they're logged out for a little bit. Also, you could accidentally log out a user that's currently active.

  • Ah, I see. I will update the code to add Variables to start method. These users are not actual Platform users so they only be logging in to Portal community page only when they have to report an event. They won't be logged in for over 30 minutes to report an event. I will update the results after an hour. Thanks!
    – Saaki
    Commented Mar 15, 2021 at 20:03
  • Looks like it solved the problem, I moved the variables inside the execute method. Thank you!!
    – Saaki
    Commented Mar 15, 2021 at 22:22

EDIT: 0 0 * * * ? is the correct cron expression as sfdcfox pointed out.

Read as "the first second of the first minute of every hour of every day of the month of every month (with the question mark being used to ignore the Day_of_week)"

I should do a better job of looking at the Salesforce documentation, they lay out the template right there:

Seconds Minutes Hours Day_of_month Month Day_of_week Optional_year

I believe you want 0 * * * * as your cron expression.

Read as: the first minute of every hour, of every day of the month, of every month, and every day of the week. Year is optional, so it is not indicated at the end of the expression.

Salesforce has a few examples and some description of cron syntax in their documentation but I would use something like crontab.guru or a cron expression generator to help generate them.

I am wondering though as to why you would want to deactivate users after such a short length of time. You don't mean to simply log them out right? If so you can do that with some configuration - no code necessary.

  • 1
    Good guess, but there's another problem at hand.
    – sfdcfox
    Commented Mar 15, 2021 at 19:47
  • These users won't be actual platform users, we are using community pool license who gets activated whenever they hit portal, we want to resuse the licenses. I will try the above Cron Expression with one zero. Thanks!
    – Saaki
    Commented Mar 15, 2021 at 19:49
  • 1
    Also, this cron expression is wrong. It's trying to schedule for every single minute of every hour. 0 0 * * * ? is the correct expression for hourly execution.
    – sfdcfox
    Commented Mar 15, 2021 at 19:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .