What’s on our mind: Automatically delete inactive users in Koha
Last updated on: 15th July 2026| 15th July 2026 | Aude Charillon | Koha
There are many reasons why you may want to delete your inactive users in Koha: to clean up data you don’t need, to find active user records more quickly, and of course for data protection compliance. And to save yourself time and effort, it’s even better to automate the process!
Automation means setting up scripts to run in the server crontab. If you don’t have server access (which, for security reasons, will be the case if we host your Koha system), simply contact your supplier (if it’s us: log a support ticket) with your requirements.
The Koha community script to batch delete user accounts is delete_patrons.pl. However, to delete the maximum number of users automatically while still making sure these are the correct users to be deleted, there are several steps to go through.
Step 1: identity users for deletion
We need a way to identify which inactive user accounts should be deleted.
What does “inactive” mean for your library? (See also our blog post: What do we mean by ‘activity’ in Koha)
- Is it based on the account expiry date? If so, how long after an account becomes expired should it be deleted?
- Is it based on the account last seen date? If so, how long after its last activity should an account be deleted?
Can these inactive library members all be listed with an SQL report? If that’s the case: great, we’ll be able to automate everything.
Or does the list have to be recouped manually with other information outside Koha? If you want to check your Koha inactive users for activity in another library platform, e.g. online resources, you will need to perform a manual step in the deletion process.

Step 2: move the users to a new category
You will need this step if you are manually deciding which users should be deleted (see last paragraph in step 1) or if you use overdue charges (see step 4). For other cases, this is an optional step – which you can still choose to perform to make things clearer.
Create a new patron category
Create a patron category specifically for those users to be deleted:
- Go to Administration > Patron categories > New category.
- For example, let’s create one with code = PDEL ; category name = Users to delete.
- You will have to add an enrollment period and a category type (these are required fields) even though they will not be significant for this category. For example, fill in enrollment period = 99 months; Category type = Adult.
Move users into the new category
Modify the users to move them into the new category.
Manually: either from your Koha SQL reports results or using a file listing all borrowernumber / cardnumber.
- Use the Batch patron modification.
- Set Patron category = Users to delete.
Automatically: using the Update patron categories script update_patrons_category.pl.
Note: if you want to automatically move users from any of your user categories to “Users to delete”, you will need to repeat the script for each user category.
- Set it to run nightly.
- Add the SQL identifying your users to delete to the
--whereparameter. - Example script parameters to move Adult users whose last seen date is over 2 years ago to the “Users to delete” category:
update_patrons_category.pl --from=ADULT --to=PDEL --where "lastseen < '`date -d '-24 month' --iso-8601`'" --confirm
Step 3: deal with outstanding loans
The delete_patrons.pl script does not delete users with outstanding loans. This could be a feature you actually want to make use of (e.g., if you still want to retain inactive users with loans) – or it’s a hurdle to get over before the users can actually be deleted (because they have been inactive for so long anyway, and the items are way overdue).
If the latter, here is how to automatically return outstanding loans – using the long overdue process.
Set your DefaultLongOverdueLostValue and DefaultLongOverdueDays system preferences.
- For example: “by default, set the LOST value of an item to [Long overdue (Lost)] when the item has been overdue for more than [185] days.”
- Optional: set the DefaultLongOverduePatronCategories system preference to [Users to delete]. This will limit the automated long overdue process to the ticked user category.
Set the Long overdue script longoverdue.pl to run nightly (or ask your support supplier to do so), after update_patrons_category.pl.
- The script automatically returns items on loan which have been overdue for more than the number of days you specified in the DefaultLongOverdueDays system preference, and applies your chosen Lost status to these items.
- Example script parameters to deal (according to the DefaultLongOverdue system preferences) with items that became overdue in the last 25 years:
longoverdue.pl --maxdays 9125 --mark-returned --confirm
Step 4: deal with outstanding charges
The delete_patrons.pl script does not delete users with outstanding charges or credits. Again, this could be a feature you want to make use of – or you want to delete these users anyway.
If the latter: after all items are returned (step 3), you can automatically write off the unpaid fines using the Batch write-off charges script writeoff_debts.pl.
- Set it to run nightly shortly after longoverdue.pl.
- Apply it only to accounts in the “Users to delete” category.
- Example script parameters to write off any charges for Users to delete:
writeoff_debts.pl --category-code PDEL --confirm
Note: using a dedicated user category (as set up in step 2) is the surest way to only apply this script to your users identified for deletion.
Users who are in credit will have to be dealt with manually, as there is currently no script to write off credits (see Bug 38059 Write off credits automatically).

Step 5: delete the users!
Now, finally, we can configure the Batch delete patrons script delete_patrons.pl to automatically delete the users.
Set the script to run automatically nightly, after longoverdue.pl and writeoff_debts.pl. Example script parameters to delete accounts in the “Users to delete” category:
delete_patrons.pl --category_code PDEL --confirm
- This will delete accounts with: holds, ILL requests, suggestions, restrictions. Note: you can add a parameter to not delete users with a specified restriction type.
- It will not delete accounts: who are guarantors for other accounts; with loans; with money owing or in credit; with the protected flag; with staff permissions.
You may not need to use the PDEL user category here: the script takes parameters for the expiry date and the last seen date. However, if you have needed or wanted to use it in previous steps, you should keep on using it. (See also: Bug 39515 Add where parameter to delete_patrons.pl)
Step 6: delete the deleted users…
And here you were, thinking we were done with step 5! But no…
In Koha, deleted accounts are moved to the deletedborrowers table. You can automatically delete your deleted users using the Clean up database script cleanup_database.pl with the parameter --deleted-patrons.
It is recommended to run cleanup_database.pl daily, to keep your database trim and help you comply with data protection regulations. You likely have this script running already with some of its many parameters. If your system is hosted by us, we will have shared with you information about our default parameters, which include fully deleting deleted users after 14 days.
Example script parameters to remove user accounts deleted over 7 days ago:
cleanup_database.pl --deleted-patrons 7 --confirm

Step 7?
I did mention several caveats, reasons why users will not be automatically deleted. As a step 7, you could run your Koha SQL report or perform a patron search for remaining “Users to delete” accounts and check why they have not been caught by the scripts. It is likely you will need to manually delete these outliers.
The end
It may seem like a long process, but once the scripts are set it’s all automated (or mostly, depending on your requirements) – and there is nothing else for you to do!
If you are an Open Fifth customer and would like more information about this process, please log a support ticket. If you are not hosted by us, do ask your questions on the Koha community’s Mattermost chat.
Blog post featured image: Cyathea dealbata by Krzysztof Ziarnek, Kenraiz published under the Creative Commons Attribution-Share Alike 4.0 International license. (Source: Wikimedia Commons)
Illustrations within the post by Peggy und Marco Lachmann-Anke (Source: Pixabay)
What’s on our mind: How CI/CD keeps code quality up