Password Policy History causes out of memory error upon installation

Created on 5 June 2025, 3 days ago

Problem/Motivation

If you install the module on a site with a lot of users (in this case over 125,000) then PHP runs out of memory, even if it has more than 1GB memory_limit.

Steps to reproduce

  1. Have a site with over a hundred thousand users.
  2. Try to enable the Password Policy History module.

Proposed resolution

I suspect it's because the install hook loads all of the users into memory:

function password_policy_history_install() {
  // Add current user passwords.
  $users = User::loadMultiple();
  $connection = Database::getConnection();

  foreach ($users as $user) {
    $hashed_pass = $user->getPassword();
    if ($hashed_pass) {
      $values = [
        $user->id(),
        $hashed_pass,
        \Drupal::time()->getRequestTime(),
      ];
      $connection->insert('password_policy_history')
        ->fields(['uid', 'pass_hash', 'timestamp'], $values)
        ->execute();
    }
  }
}

Perhaps it could instead loads them one at a time.

Remaining tasks

User interface changes

API changes

Data model changes

🐛 Bug report
Status

Active

Version

4.0

Component

Code

Created by

🇬🇧United Kingdom Rob230

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @Rob230
  • 🇬🇧United Kingdom Rob230

    I tried making it load each user individually. It still ran out of memory. Then I added a call to resetCache(), because entities appear to be statically cached in PHP. This made it stop running out of memory, but it caused the installation of the module to take very long time. I suspect the time it took would be an issue for anyone enabling the module in the backend, rather than via the command line.

    Instead of doing this in an install hook, I think it should be done in a deploy hook, using a batch. The problem with that is I think deploy hooks are only available to people with drush.

    The patch I'm attaching did work for me - it was able to install the module successfully without running out of memory, but it took over 5 minutes (with drush), so I suspect if you enabled the module in the backend it would cause a 504 error (gateway timeout) or hit PHP's max_execution_time for most common server set ups.

Production build 0.71.5 2024