How to limit users to a create only one instance of a node type?
FWIW I've been using Node Limit on a dev site for a few weeks now, it's had thorough testing and seems to work perfectly. I'm using the 'Node Limit Type' and 'Node Limit User of Role' sub-modules.

If you want to implement it yourself, you can't really look anywhere better than inside the Node Limit module itself. It implements hook_node_prepare() to deny access to the node add form if the user has exceeded the maximum nodes, based on various rules.

A very simple custom implementation might look like this:

function MYMODULE_node_prepare($node) {
  if (empty($node-&gt;nid) &amp;&amp; $node-&gt;type == 'the_content_type') {
    // Grab the number of nodes of this type the user has already created.
    $args = array(':type' =&gt; 'the_content_type', ':uid' =&gt; $GLOBALS['user']-&gt;uid);
    $node_count = db_query('SELECT COUNT(nid) FROM {node} WHERE type = :type AND uid = :uid', $args)-&gt;fetchField();

    // Get the max allowed number of nodes
    $limit = function_to_get_limit();

    // If the user is at/has exceeded the limit, set a message and send the user
    // off somewhere else.
    if ($limit &gt;= $node_count) {
      drupal_set_message(t('Node limit exceeded'));

      drupal_goto('somewhere');
    }
  }
}


You could obviously add further checks in there to make sure the user has a certain role, etc. I'd advise having a flick through the code in the Node Limit module to see how the above could be improved upon.

The above is a 'friendly' way to perform the check (i.e. one that doesn't just throw out a 403 page). If you want to be more militant, you could put roughly the same code in a hook_node_access() implementation instead:

function MYMODULE_node_access($node, $op, $account) {
  if ($op == 'create' &amp;&amp; $node-&gt;type == 'the_content_type') {
    // Grab the number of nodes of this type the user has already created.
    $args = array(':type' =&gt; 'the_content_type', ':uid' =&gt; $account-&gt;uid);
    $node_count = db_query('SELECT COUNT(nid) FROM {node} WHERE type = :type AND uid = :uid', $args)-&gt;fetchField();

    // Get the max allowed number of nodes
    $limit = function_to_get_limit();

    // If the user us at/has exceeded the limit, set a message and send the user
    // off somewhere else.
    if ($limit &gt;= $node_count) {
      return NODE_ACCESS_DENY;
    }

    return NODE_ACCESS_ALLOW;
  }

  return NODE_ACCESS_IGNORE;
}