Build StackExchange-style url's
I wrote a custom module to do this very thing. I use Pathauto to automatticly create aliases for my nodes, in the form of questions/123/title-of-node-here. The following code creates a /custom404 page. I configure my "Default 404 (not found) page" (in Site information) to custom404. The module picks the node id out of the url, checks for its existence, and then redirects to node/%nid. Finally, the Global Redirect module will take over and redirect the user to the canonical url.

/**
 * Implements hook_menu().
 */
function custommodule_menu() {
  $items = array();

  $items['custom404'] = array(
    'title' =&gt; 'Page not found',
    'access callback' =&gt; TRUE,
    'page callback' =&gt; 'custommodule_page',
    'type' =&gt; MENU_LOCAL_TASK
  );

  return $items;
}


function custommodule_page() {
  $path = _custommodule_request_path();
  $parts = explode('/', $path);

  // The following lines matche a path alias to a content type
  // map /questions/%nid/%title to the 'question' content type
  _custommodule_match_nid($parts, 'questions', 'question');  
  // map /websites/%nid/%title to the 'website' content type
  _custommodule_match_nid($parts, 'websites', 'website');

  drupal_set_title(t('Page not found'));
  return ' ';
}

/**
 * custommodule_request_path() is copied from globalredirect_request_path
 */
function _custommodule_request_path() {
  if (isset($_SERVER['REQUEST_URI'])) {
    if (isset($_REQUEST['q'])) {
      $path = $_REQUEST['q'];
    }
    else {
      // This is a request using a clean URL. Extract the path from REQUEST_URI.
      $request_path = strtok($_SERVER['REQUEST_URI'], '?');
      $base_path_len = strlen(rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/'));
      // Unescape and strip $base_path prefix, leaving q without a leading slash.
      $path = substr(urldecode($request_path), $base_path_len + 1);
    }
  }
  else {
    // This is the front page.
    $path = '';
  }

  // Under certain conditions Apache's RewriteRule directive prepends the value
  // assigned to $_GET['q'] with a slash. Moreover we can always have a trailing
  // slash in place, hence we need to normalize $_GET['q'].
  $path = ltrim($path, '/');

  return $path;
}

function _custommodule_match_nid($parts, $path_root, $node_type) {
  if (count($parts) &gt;= 2 &amp;&amp; $parts[0] == $path_root &amp;&amp; ctype_digit($parts[1])) {
    $id = $parts[1];
    $args = array(
      ':nid' =&gt; $id,
      ':type' =&gt; $node_type,
    );
    if (db_query('SELECT count(nid) FROM {node} WHERE nid = :nid AND type = :type AND status = 1', $args)-&gt;fetchField()) {
      if ($alias = drupal_get_path_alias('node/'.$id)) {
        _custommodule_goto($alias);
      }
    }
  }
}

function _custommodule_goto($path) {
  $options = array(
    'fragment' =&gt; '',
    'query' =&gt; NULL,
    'absolute' =&gt; FALSE,
    'alias' =&gt; FALSE,
    'prefix' =&gt; '',
    'external' =&gt; FALSE,
  );
  unset($_GET['destination']);
  drupal_goto($path, $options, 301);
}