I think the most secure approach is to store a random id in the database and to also sign it any time it’s exposed to the user (as a cookie or url sent via email). The first benefit is that you won’t be exposed to DoS attacks whereby you’re querying non-existent tokens from your database, and the second benefit is that illegitimate sessions can only be established by compromising both your database sessions table and your application’s signing secrets.