Check if the user has read a node, if so give access to the next
I'd say you can use hook_ENTITY_TYPE_view to store the uid and the nid of the user into a custom table. That would solve the easy part, I believe.
You'd may start by something similar to
function yourmodule_node_view(array &amp;$build, \Drupal\Core\Entity\EntityInterface $entity, 
        \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode) {

  $bundle = $entity-&gt;bundle();
  if($bundle == 'your_content_type') {
    $uid = \Drupal::currentUser()-&gt;id(); // get current user's ID
    $nid = $entity-&gt;get('nid');
    [...] // insert into custom table, etc
  }
}

For the long-term, complex solution regarding performance, that's a huge discussion. If your node list is just a simple queue that unlocks next node if previous has been read, then maybe storing just the current nid would work for you. If you need the history per user, then, as mentioned, some different solutions could do the trick. Other approach could be to do database sharding, for instance creating 1 table per node so table_read_nid_1 would just contain the users who actually have read this node and can unlock the second. table_read_nid_2 would contain the next and so on. Don't be afraid of sharding, lots of big companies use it daily! :)