This article discusses the holds lifecycle, including system settings, placing, filling, and modifying holds, holds-related notices, working with hold logs, and more. We encourage you to use the Table of Contents to jump to a specific section or Control+F to search for keywords.
Hold policies
Your library's circulation and fine rules determine who can place holds, what types of items they can place on hold, how many holds they can place, for how long filled holds are available, and more. In Administration > Circulation and fine rules, review the following guidelines from the Koha manual:
When setting your library's hold rules, keep in mind that staff can place holds by override if the system preference AllowHoldPolicyOverride is set to 'Allow'. Koha will not fill holds placed by override if they are forbidden by 'Holds policy by item type' settings, but it will fill holds that are placed by override in violation of rules in the circulation
matrix or 'Checkout, hold policy by patron category' settings. Please see 'Placing holds by override' below for further details and examples.
Note that in addition to the maximum numbers of holds above, a global maximum is set in the maxreserves system preference. Make sure that the maxreserves number is set properly in addition to any limits in your circulation and fine matrix.
Note
that for libraries whose circulation and fine rules allow patrons to
place more than one hold at a time on the same record with the 'Holds to
place (count)' column, the type of hold (bib or item) chosen for
the patron's first hold determines the type for any additional holds on
that record. This means that if staff place a bib-level hold for a
patron on a title, and then place a second hold for them on that same
record, the second hold (and any additional) must be bib-level.
Likewise, if the first hold a patron places on a title is item-level,
any additional holds they place on that same bib must be item-level.
Placing holds by override
As noted above, staff will be able to place holds by override if the system preference AllowHoldPolicyOverride is set to 'Allow'. However, Koha handles overrides differently depending on their type.
Koha will not fill holds that are forbidden by 'Holds policy by item type' settings. If a hold is forbidden by those settings, any invalid pickup locations will be flagged with a exclamation mark in a black circle:
Holds that are placed by override that violate rules in the circulation matrix or 'Checkout, hold policy by patron category', however, will fill. If the bib contains no items that the patron can place on hold, there will be a message at the top of the holds screen:
If there are only some items on which patrons cannot place holds per the circulation matrix, there will be no 'Cannot place holds' message, but those individual items will be marked with an exclamation mark in a yellow triangle:
Both of these holds will fill, since they violate rules in the circulation matrix or 'Checkout, hold policy by patron category' but not 'Holds policy by item type' settings.
Non-priority vs. lowest-priority holds
Although their names sound similar, these two features serve different purposes.
Non-priority holds
When
staff are placing a hold, they have the option to mark it as a 'Non
priority hold'. As the hold screen indicates, checking this box means
that the hold will not prevent existing checkouts from renewing. This
can be useful for items that need to return to Technical Services for
recataloging or for non-urgent repairs such as fixing a label.
Non-priority holds will be noted in the 'Details' column of the holds
table:
As indicated above, non-priority holds do not affect the patron's
place in line. Any holds placed after the non-priority hold will be
below them on the list, just like any other hold.
Once
a hold has been placed with 'Non priority hold' selected, the selection
cannot be undone. If the hold should be 'normal', staff would need to
cancel the hold and re-place it without 'Non priority hold' checked.
Lowest-priority holds
Lowest-priority
holds are a way to 'pin' a patron to the bottom of the holds list, even
if other patrons place holds after them. As noted in the manual,
this can be useful for homebound or books-by-mail patrons, for
instance, who may have longer loan periods than standard patrons.
Unlike
non-priority holds, lowest-priority can only be selected after a hold
has been placed, and it does not prevent checkouts from renewing. Also,
the lowest-priority toggle can be de-selected if it is no longer needed.
In combination
If staff needs an item, but they don't want the staff hold to prevent renewals and they
want any patron holds to be filled first, they can select 'Non priority
hold' when placing the hold and then also toggle the hold for lowest
priority once it has been placed:
Staff can change the pickup location for patrons' unfilled holds from the Holds tab of the bib using the 'Pickup library' column, or from the 'Pickup at' column in the Holds tab from patrons' Checkout or Details tabs. Changes to the pickup location from the patron's account will be automatically saved. If the change is made from the Holds tab of the bib, staff must click the 'Update holds' button to save the new location:
If staff tries to change the pickup location of a hold to an invalid library, they will see the same black circle with a white exclamation mark noted above for placing holds:
The manual discusses options for suspending and unsuspending holds from the bib and from patron accounts. Note that if a patron has multiple holds that they want to suspend or unsuspend, staff can process all of them at once from the Holds tab in the Details or Checkout section of the patron's account, rather than one by one from the bib:
Filling holds
Holds can be filled in Koha when items are checked in, or by the library running a built-in report to generate a list of items on the shelves that patrons have requested. Staff would then check those items in to fill holds. The two built-in options are called Holds queue and Holds to pull. Since Holds to pull has no way to account for multiple libraries owning
the requested item, ByWater recommends that libraries with multiple
locations use the Holds queue. Single-site libraries can also use the Holds queue, but Holds to pull should not be used by libraries with multiple locations.
Please see the Koha manual's discussion of how the holds queue is built, how to run it, and what system preferences to consider.
Generally, when the holds queue is built, Koha looks at the following places (in order):
LocalHoldsPriority system preference
Item level holds
HoldsQueuePrioritizeBranch system preference
Transport Cost Matrix (if using)
StaticHoldsQueueWeight system preference
Free for all!
If your library is not using the real-time holds queue, you can
choose how often the cron job that builds the holds queue is run - for
instance, every 15 minutes or hourly. ByWater partners who are unsure of
their settings or timing are encouraged to submit a ticket so that we
can confirm.
The holds queue will default to the staff member's logged-in library, and they can optionally filter the report by item type, shelving location, and/or collection code.
Staff can sort the report by any column by clicking on the column name. For instance, it can be useful to sort by shelving location or call number so that all items in the same area are displayed together:
Staff can also type in the blank row under the header columns to filter. This is useful if, for instance, your library prints the report and wants to give specific shelving locations to different staff members:
Holds to pull
Please see the manual for details on using the Holds to pull report. Note that this table can also be sorted by clicking on column headers, and filtered by making a selection or typing in the field below each header.
If your library is not seeing the expected number of holds, it is likely due to the dates set in the 'Refine results' box. As the manual notes, the default range is set in system preferences HoldsToPullStartDate and ConfirmFutureHolds, but libraries can run the report for a wider range by changing dates in the 'Refine results' box. For instance, a library may want to occasionally run the report for 365 days to make sure that holds placed for titles with a long wait are included.
For ByWater partner libraries, HoldsToPullStartDate is set to 30 and ConfirmFutureHolds at 0 by default, which means that holds to pull will look for holds placed 30 days ago through the current date. The ideal range depends on the library - libraries with long hold lists may want a longer range than libraries who only tend to have one or two holds on a title at a time.
For holds that have been suspended and later unsuspended, note that Holds to pull only looks at the date a hold was placed, not the date it was unsuspended. For instance, if HoldsToPullStartDate is set to 30, and a hold was unsuspended 15 days ago but originally placed 60 days ago, it will not show up on Holds to pull. Staff would need to change the 'Start date' in 'Refine results' to capture that unsuspended hold.
In addition to the ability to mark an item as lost (and optionally notify the patron) with the 'Mark item as lost'/'Mark lost and notify patron' button in the 'Action' column, staff can cancel holds by clicking 'Cancel hold'. If they select a reason, the patron will receive the 'Hold cancellation' notice.
Filled holds
Holds awaiting pickup
Holds that have been filled will appear on the 'Holds awaiting pickup' report in the Circulation module. By default, each tab will be sorted by the 'Waiting date' column. If allowed per your library's 'Default waiting hold cancellation policy', filled holds that patrons have requested be cancelled will show on the 'Holds with cancellation requests' tab. Note that those holds must still be cancelled by staff (please see below for details on cancelling filled holds).
Please see 'Manually cancelling expired waiting holds' for details on how to cancel filled holds.
Managing filled holds
Changing expiration dates
Libraries can change the expiration date on a filled hold from the Holds tab of the bib. For instance, if a patron's item will be held until Tuesday but they call and ask that it be held until Thursday, the library can extend the date.
From the bib, click on the date in the 'Expiration' column and select the new date. Be sure to click 'Update hold(s)' to save:
To print a new hold slip with the updated expiration date, click 'Print slip' in the 'Print hold/transfer slip' column:
Don't check the item in to print a new slip! Doing so will reset the expiration date to where it was originally calculated.
Reverting filled holds
If staff realizes that an item is damaged or otherwise shouldn't circulate after a hold is filled, they can revert the hold to un-fill it and retain the patron's place in line:
Cancelling holds
Unfilled holds
Cancelling from the staff interface
Please see the manual for how staff can cancel/delete unfilled holds from the bib. Note that staff will see a popup to confirm deletion, and to optionally send the patron a cancellation message:
If
a reason is selected, the patron will receive notice of the
cancellation. If no reason is selected, they will not receive a notice
informing them that the hold has been cancelled.
If
a patron needs to cancel multiple holds, staff can do so from the Holds
tab of the Checkout of Details sections of their account. They would
select 'Yes' in the 'Delete?' column for all holds that should be
cancelled, and then the 'Cancel marked holds' button. As above, the
patron will be notified of the cancellation only if a reason is
selected:
Cancelling from the staff interface (Update coming week of 10/27/25)
If
a patron needs to cancel multiple holds, staff can do so from the Holds
tab of the Checkout of Details sections of their account. They can multi-select the column for either specific holds or select all holds, and then the 'Cancel marked holds' button. As above, the
patron will be notified of the cancellation only if a reason is
selected:
multiselect holds
Automatically cancelling expired unfilled holds
There are two ways to have Koha automatically cancel expired unfilled holds.
Preferred: If your library is using the DefaultHoldExpirationdate group of system preferences, we recommend using the cancel_expired_holds.pl cron to cancel holds beyond the date set by DefaultHoldExpirationdate and beyond patron-set expiration dates. If you do not also want to cancel expired filled holds, make sure that ExpireReservesMaxPickupDelay is set to “Don’t allow”.
Alternate: If you do not want to use the DefaultHoldExpirationdate set of system preferences, the cancel_unfilled_holds.pl cron can cancel expired holds that are past their patron-set expiration date and past a number of days set in the cron. However, since this expiration date won't be visible in the hold, we recommend using the Preferred method above.
Both cancel_expired_holds.pl and cancel_unfilled_holds.pl will cancel suspended holds.
Both of these crons can be set to automatically notify the patron about the cancellation using the HOLD_CANCELLATION notice.
To confirm whether these crons are running, as well as any relevant settings such as notifications or the number of days for cancel_unfilled_holds.pl, ByWater partners can submit a ticket.
Filled holds
Automatically cancelling expired waiting holds
Koha can be set to automatically cancel filled holds that have passed their expiration date. To do this, set the system preference ExpireReservesMaxPickupDelay to “Allow” and confirm that the cancel_expired_holds.pl cron is
running. ByWater partners can submit a ticket to confirm whether it is
running for your library.
If your library wishes to send patrons a notice telling them that their hold has been cancelled because it has expired, please include the reason for cancellation from your HOLD_CANCELLATION authorized values that should be in the 'Hold cancellation' (code HOLD_CANCELLED) notice. If no reason is set in the cancel_expired_holds.pl cron, a notice will not be sent.
This will also cancel unfilled holds whose patron-set expiration date or the expiration date set by the DefaultHoldExpirationdate group of system preferences has passed.
Note: if a library has ExpireReservesMaxPickupDelay set to “Allow”, they can also choose whether to allow holds to automatically cancel on closed days with the system preference ExpireReservesOnHolidays.
Manually cancelling expired waiting holds
Many
libraries choose not to automatically cancel expired filled holds.
Instead, they prefer to check these items in to cancel at the time that
they remove them from the hold shelf. The benefit of this workflow is
that checking the item in to cancel will also prompt them to fill any
additional holds on the item.
To cancel filled holds that are beyond their expiration date or at a patron's
request, ByWater does not recommend using the 'Cancel hold',
'Cancel selected' or 'Cancel all' buttons on 'Holds waiting', 'Holds
waiting past their expiration date', and 'Holds with cancellation
requests' tabs of 'Holds awaiting pickup', or cancelling from the bib or
patron account. Doing so will
not automatically prompt to fill any additional holds for that title
until the item is also checked in, so canceling using one of those methods means extra work for staff.
Instead, we recommend checking items in to cancel filled holds. Doing so will
prompt staff with this screen:
Once they click 'Cancel hold' (with a reason to notify the patron, if desired), the next hold will pop up automatically:
If
there are no additional holds, staff will see the normal 'Check in'
screen, so they can easily continue checking in any additional holds
that need to be cancelled.
Note that a notice will only be sent informing the patron of the hold's cancellation if a reason is selected - otherwise, they will not be notified.
Hold notifications
For details on built-in hold notices, please see the manual.
Filled holds
Depending on what patrons have set for their messaging preferences,
patrons will receive the 'Hold filled' (code HOLD, or HOLDDGST for the
Digest version) notice by email, SMS, and/or phone when a hold has been
filled for them. Libraries can also set up the 'Hold reminder' (code
HOLD_REMINDER) notice to send if patrons have not picked up their hold a
given number of days after it has been filled, but before it has
expired. The option to receive that notice is also in patrons' messaging
preferences, but the number of days at which patrons should receive the
notice is set in the holds_reminder.pl cron.
The notice can either send once when a hold has not picked up X number
of days after it was filled, or every day starting on X day until it is
either picked up or expires. For instance, if items are held for 7 days,
a library could have the cron set so that the 'Hold reminder' notice
sends on day 4 if the hold isn't picked up. Or, they could have it set
to send on day 4, 5, 6, and 7.
Hold cancellations
Libraries
can have a 'Hold cancellation' (code HOLD_CANCELLATION) notice sent
when holds are cancelled. Please see the 'Cancelling holds' section for
details on how this can be triggered to send.
Like many other notices, HOLD_CANCELLATION can be written with Template Toolkit to give it added flexibility. For instance, a library might want to add a line stating that if a hold was cancelled due to a damaged item and a replacement copy is ordered, a hold will be placed at that time. That would look like this:
If our selectors choose to order a replacement copy of this title, we will place a new hold for you at that time.
[% END %]
Thank you,
[% branch.branchname %] Staff
The section that starts with "IF" and runs through "END" is a basic example how Template Toolkit can make the email different based on which reason was selected. This example includes a sentence that only goes into the email if the "DAMAGED" reason was selected. For any other reason, those lines are skipped entirely. The example above would look like this:
If a library is using Holds to pull and has set CanMarkHoldsToPullAsLost to 'Mark lost and notify the patron', they can send 'Hold has been
cancelled' (code CANCEL_HOLD_ON_LOST) when cancelling a hold.
Understanding hold expiration dates
A hold’s expiration date can be calculated or set in a few different ways in Koha.
Default expiration date
Koha
can be configured so that a default hold expiration date is set when
holds are placed. If set, this is the number of days after which a hold,
if still unfilled, should be considered expired.
The system preferences for this are DefaultHoldExpirationdate (“Set” or “Don’t set”), DefaultHoldExpirationdatePeriod (a number), and DefaultHoldExpirationdateUnitOfTime (“days”, “months”, or “years”). For instance, if a library wants holds
to have a default expiration date of one year from the date the hold is
placed, these would be set as “[Set] default expiration date for holds
automatically. If enabled, set expiration date [1] [year] from reserve
date.”
Patron-set expiration date
Patrons
can set a “hold not needed after” date when placing holds from the
OPAC. This can be useful if, for instance, a patron wants a book to take
on vacation, so if the item isn’t available by the time they leave,
they no longer want it. This date is stored and visible in logs in
reserves.patron_expiration_date.
When patrons place holds, this date will be optional unless the system preference OPACMandatoryHoldDates is set to “When placing a hold from the OPAC, make [both dates] or [an end date] mandatory.”
Note
that if a patron sets a “hold not needed after” date and then the hold
is filled, the earlier of the patron-set expiration date and the date
calculated using the number in ReservesMaxPickUpDelay (or the
‘Holds pickup period (days)’ column) will be set in
reserves.expirationdate as the expiration date for pickup. For example: a
library has ReservesMaxPickUpDelay set to 7 days, and a patron
places a hold with 7/7 as the “hold not needed after” date. When the
hold is filled on 7/3, the expiration date for the hold will be 7/7, not
7/10, because Koha is using the earlier of the two expiration dates.
Filled holds
Most
commonly, “expiration date” refers to the last day that an item will be held for a patron once the hold is filled. This is
determined in one of three ways:
The system preference ReservesMaxPickUpDelay sets a global number of days that items are held once a hold is filled. This works in combination with ExcludeHolidaysFromMaxPickUpDelay,
which tells Koha whether to exclude days marked as closed on the
calendar (“Use the calendar”) or include closed days (“Ignore the
calendar”) in counting up to the number set in ReservesMaxPickUpDelay.
If
there are item types that should be held for a different number of days
than the default, libraries can set a custom number in the circulation
matrix using the ‘Holds pickup period (days)’ column for that
library/patron category/item type combination.
A
patron-set “hold not needed after” date, if earlier than the date
calculated using one of the methods above, will be set as a filled
hold’s expiration date. This is discussed in more detail above.
In general, items will be held for the number of days in ReservesMaxPickUpDelay unless a custom number is set in the circulation matrix. For instance, if ReservesMaxPickUpDelay is set to 7 but hotspots are only held for 3 days, the library would
set all circulation rules for hotspots to 3 in the ‘Holds pickup period
(days)’ column and leave the column set to Default for all other rules.
Once a hold is filled, its expiration date is visible in logs in reserves.expirationdate.
Hold history
Staff interface
The manual addresses how to make hold history visible for staff in patron accounts.
Hold logs
Koha's action logs are powerful tools for solving circulation mysteries, but using them to view hold activity requires an extra step before searching the holds log. For searching circulation logs and cataloging logs, we can use borrowernumber or biblionumber as the object to see the respective history, but the holds log uses a unique identifier that is harder to find: the reserve_id.
Like all logs in Koha, the holds log must first be enabled. That is controlled by the HoldLog system preference and is typically a log we have turned on by default in ByWater partners' sites.
With that enabled, you need a way to find the reserve_id. If you have
the patron's card number and the bib's biblionumber, you can find the
reserve_id using this report:
select biblio.title, holds.reserve_id from (select borrowernumber, biblionumber, reserve_id from reserves union select borrowernumber, biblionumber, reserve_id from old_reserves) holds left join borrowers using (borrowernumber) left join biblio using (biblionumber) where borrowers.cardnumber=<<Enter cardnumber>> and holds.biblionumber=<<Enter biblionumber>>
We recommend saving this in your reports module for future holds troubleshooting!
We further recommend not limiting by date or specific action when searching logs
by reserve_id, since you will typically want to see its entire
history. Select only Holds for the Module, and enter the reserve_id in the Object field:
Here is an example of results:
Read hold logs from the bottom up, as the oldest entries will be at the bottom. For this example, we can see that the hold was placed on 7/7, suspended ('suspend' =>1), and then unsuspended ('suspend' =>0). It then had its pickup location changed from M to E ('branchcode' => 'E'), was found and put into transfer ('found' => 'T'), and set to waiting once it arrived at E ('found' => 'W'). Finally, it was cancelled (Cancel in the 'Action' column, and 'cancellationdate' => '2025-07-07 14:48:11').
Hold logs can help libraries identify who cancelled or modified holds, when expiration dates were added or changed, whether pickup locations changed (and by whom), and more. Since the name of the logged-in staff member shows in the 'Librarian' column, they can also help identify who made a change. They can also provide useful data points for identifying hold-related bugs. They won't solve every holds-related mystery, and they aren't a substitute for talking with staff about the context of why actions were taken, but they can help narrow down when, where, and with whom something changed about a hold.
The manual discusses how patrons can see their current holds in the OPAC.
If patrons have set a “hold not needed after” date, that date will show on
their Holds tab in the OPAC in the ‘Expires on’ column. Dates set by the DefaultHoldExpirationdate group of preferences would also show
here when applicable. The date until which a filled hold will be held
will show in the ‘Status’ column.
The system preference OPACAllowUserToChangeBranch allows libraries to choose whether patrons can change the pickup location of an unfilled hold when it is pending, suspended, and/or in transit. Patrons cannot change the pickup location of filled holds.
History
Please see the manual for details on patrons' ability to see and their holds history in the OPAC. Note the following features of this section:
By default, the most recent 50 holds will show, but patrons can see
their entire holds history by clicking the 'Show all items' link.
By default, holds history will be in order by the 'Hold date' column, but patrons can choose to order it by title or author instead using the drop-down under the 'Holds history' header. They can also sort the table by any column by clicking on its header.
Patrons can use the search box to find a specific hold.
Patrons can use the 'CSV' button to export a .csv file of their holds, the 'Copy' button to copy/paste the table into a spreadsheet, or 'Print' to print their table.
Understanding the Hold Ratios Report The Hold Ratios feature is built into the Circulation module, and can also be accessed through the Acquisitions sidebar. It can assist with collection development decisions by calculating how many holds exist per ...
This articles walks through the steps of setting up a Koha to Koha interlibrary loan instance. The ILL (Interlibrary loans) module adds the ability to request and manage loans or copies of material. Patrons can submit a request via the OPAC from the ...
Does Changing An Item's Barcode Affect its Statistics? Updating an item's barcode will not affect its checkout history or statistics. Each item in Koha has a corresponding itemnumber, a persistent, unique identifier in the database. That itemnumber ...
One of the key components of your library's collection will be the Item Type designation. Item types are a way for your patrons to identify what the item is and more importantly to Koha how this item circulates in your library. Here is a link to the ...
The Koha Offline Circulation Tool that was created by Kyle Hall for Windows. The offline circulation tool for Windows will generate a KOC (koha offline circulation) file that you can upload into Koha once your system comes back up. This tool works ...