My favorite way would be to store password information as a hash chain, so old users can be immediately upgraded to the latest method while new users just use the latest.<p>For example, Django currently stores its passwords in a single database column as<p><pre><code>  &lt;algorithm&gt;$&lt;iterations&gt;$&lt;salt&gt;$&lt;hash&gt;
</code></pre>
So suppose we generalize that to a chain of one or more hash algorithms, with each output fed in as the password to the next, resulting in a final hash:<p><pre><code>  &lt;algorithm&gt;$&lt;iterations&gt;$&lt;salt&gt;|&lt;algorithm&gt;$&lt;iterations&gt;$&lt;salt&gt;|$&lt;hash&gt;
</code></pre>
For example if you had a user who logged in way back in unsalted md5 days and never logged in again, you might end up with a chain like this:<p><pre><code>  md5|sha256$&lt;salt&gt;|bcrypt$&lt;iterations&gt;$&lt;salt&gt;|$&lt;hash&gt;
</code></pre>
... and then to upgrade to argon you would grab that string, shove the final hash through argon(), and write back:<p><pre><code>  md5|sha256$&lt;salt&gt;|bcrypt$&lt;iterations&gt;$&lt;salt&gt;|argon$&lt;iterations&gt;$&lt;salt&gt;|$&lt;hash&gt;
</code></pre>
For new users, or if the old user finally came back and logged in with their correct password, you could then take the opportunity to write back a simplified version:<p><pre><code>  argon$&lt;iterations&gt;$&lt;salt&gt;|$&lt;hash&gt;
</code></pre>
Iterations could be calibrated differently depending on the chain, if the earlier steps take enough time to matter.<p>As far as I can tell this is the best possible service you can offer to the users whose long-ago passwords you&#x27;re storing, short of deleting their passwords entirely. Throwing away the earlier version and replacing it with the argon-wrapped version can&#x27;t hurt them, and will almost certainly help.<p>(Usual caveats apply about not doing things that add complexity if you don&#x27;t need it.)