diff --git a/inc/indexer.php b/inc/indexer.php
index 64e172b5b598d2f8bb9d1c841ec01049172d06c6..3b4796676729998bb72d486d2793e489b9ac50c7 100644
--- a/inc/indexer.php
+++ b/inc/indexer.php
@@ -1197,7 +1197,7 @@ function idx_addPage($page, $verbose=false, $force=false) {
         @unlink($idxtag);
         return $result;
     }
-    $indexenabled = p_get_metadata($page, 'internal index', true);
+    $indexenabled = p_get_metadata($page, 'internal index', METADATA_RENDER_UNLIMITED);
     if ($indexenabled === false) {
         $result = false;
         if (@file_exists($idxtag)) {
@@ -1215,8 +1215,8 @@ function idx_addPage($page, $verbose=false, $force=false) {
 
     $body = '';
     $metadata = array();
-    $metadata['title'] = p_get_metadata($page, 'title', true);
-    if (($references = p_get_metadata($page, 'relation references', true)) !== null)
+    $metadata['title'] = p_get_metadata($page, 'title', METADATA_RENDER_UNLIMITED);
+    if (($references = p_get_metadata($page, 'relation references', METADATA_RENDER_UNLIMITED)) !== null)
         $metadata['relation_references'] = array_keys($references);
     else
         $metadata['relation_references'] = array();
diff --git a/inc/parserutils.php b/inc/parserutils.php
index d7451cee4c1e52287779445c6a64665b800b07fc..abba89b5a4f11d54f27c91e2f6f8a107a117e793 100644
--- a/inc/parserutils.php
+++ b/inc/parserutils.php
@@ -10,20 +10,43 @@
 if(!defined('DOKU_INC')) die('meh.');
 
 /**
- * For how many different pages shall the first heading be loaded from the
- * metadata? When this limit is reached the title index is loaded and used for
- * all following requests.
+ * How many pages shall be rendered for getting metadata during one request
+ * at maximum? Note that this limit isn't respected when METADATA_RENDER_UNLIMITED
+ * is passed as render parameter to p_get_metadata.
  */
-if (!defined('P_GET_FIRST_HEADING_METADATA_LIMIT')) define('P_GET_FIRST_HEADING_METADATA_LIMIT', 20);
+if (!defined('P_GET_METADATA_RENDER_LIMIT')) define('P_GET_METADATA_RENDER_LIMIT', 5);
 
 /** Don't render metadata even if it is outdated or doesn't exist */
 define('METADATA_DONT_RENDER', 0);
-/** Render metadata when the page is really newer or the metadata doesn't exist. Uses just a simple check,
-    but should work pretty well for loading simple metadata values like the page title and avoids
-    rendering a lot of pages in one request. */
+/**
+ * Render metadata when the page is really newer or the metadata doesn't exist.
+ * Uses just a simple check, but should work pretty well for loading simple
+ * metadata values like the page title and avoids rendering a lot of pages in
+ * one request. The P_GET_METADATA_RENDER_LIMIT is used in this mode.
+ * Use this if it is unlikely that the metadata value you are requesting
+ * does depend e.g. on pages that are included in the current page using
+ * the include plugin (this is very likely the case for the page title, but
+ * not for relation references).
+ */
 define('METADATA_RENDER_USING_SIMPLE_CACHE', 1);
-/** Render metadata using the metadata cache logic. */
+/**
+ * Render metadata using the metadata cache logic. The P_GET_METADATA_RENDER_LIMIT
+ * is used in this mode. Use this mode when you are requesting more complex
+ * metadata. Although this will cause rendering more often it might actually have
+ * the effect that less current metadata is returned as it is more likely than in
+ * the simple cache mode that metadata needs to be rendered for all pages at once
+ * which means that when the metadata for the page is requested that actually needs
+ * to be updated the limit might have been reached already.
+ */
 define('METADATA_RENDER_USING_CACHE', 2);
+/**
+ * Render metadata without limiting the number of pages for which metadata is
+ * rendered. Use this mode with care, normally it should only be used in places
+ * like the indexer or in cli scripts where the execution time normally isn't
+ * limited. This can be combined with the simple cache using
+ * METADATA_RENDER_USING_CACHE | METADATA_RENDER_UNLIMITED.
+ */
+define('METADATA_RENDER_UNLIMITED', 4);
 
 /**
  * Returns the parsed Wikitext in XHTML for the given id and revision.
@@ -239,8 +262,9 @@ function p_get_instructions($text){
  * @param string $id The id of the page the metadata should be returned from
  * @param string $key The key of the metdata value that shall be read (by default everything) - separate hierarchies by " " like "date created"
  * @param int $render If the page should be rendererd - possible values:
- *     METADATA_DONT_RENDER, METADATA_RENDER_USING_SIMPLE_CACHE, METADATA_RENDER_USING_CACHE, default:
- *     METADATA_RENDER_USING_CACHE
+ *     METADATA_DONT_RENDER, METADATA_RENDER_USING_SIMPLE_CACHE, METADATA_RENDER_USING_CACHE
+ *     METADATA_RENDER_UNLIMITED (also combined with the previous two options),
+ *     default: METADATA_RENDER_USING_CACHE
  * @return mixed The requested metadata fields
  *
  * @author Esther Brunner <esther@kaffeehaus.ch>
@@ -248,6 +272,10 @@ function p_get_instructions($text){
  */
 function p_get_metadata($id, $key='', $render=METADATA_RENDER_USING_CACHE){
     global $ID;
+    static $render_count = 0;
+    // track pages that have already been rendered in order to avoid rendering the same page
+    // again
+    static $rendered_pages = array();
 
     // cache the current page
     // Benchmarking shows the current page's metadata is generally the only page metadata
@@ -265,22 +293,26 @@ function p_get_metadata($id, $key='', $render=METADATA_RENDER_USING_CACHE){
 
     // prevent recursive calls in the cache
     static $recursion = false;
-    if (!$recursion && $render != METADATA_DONT_RENDER && page_exists($id)){
+    if (!$recursion && $render != METADATA_DONT_RENDER && !isset($rendered_pages[$id])&& page_exists($id)){
         $recursion = true;
 
         $cachefile = new cache_renderer($id, wikiFN($id), 'metadata');
 
         $do_render = false;
-        if ($render == METADATA_RENDER_USING_SIMPLE_CACHE) {
-            $pagefn = wikiFN($id);
-            $metafn = metaFN($id, '.meta');
-            if (!@file_exists($metafn) || @filemtime($pagefn) > @filemtime($cachefile->cache)) {
+        if ($render & METADATA_RENDER_UNLIMITED || $render_count < P_GET_METADATA_RENDER_LIMIT) {
+            if ($render & METADATA_RENDER_USING_SIMPLE_CACHE) {
+                $pagefn = wikiFN($id);
+                $metafn = metaFN($id, '.meta');
+                if (!@file_exists($metafn) || @filemtime($pagefn) > @filemtime($cachefile->cache)) {
+                    $do_render = true;
+                }
+            } elseif (!$cachefile->useCache()){
                 $do_render = true;
             }
-        } elseif (!$cachefile->useCache()){
-            $do_render = true;
         }
         if ($do_render) {
+            ++$render_count;
+            $rendered_pages[$id] = true;
             $old_meta = $meta;
             $meta = p_render_metadata($id, $meta);
             // only update the file when the metadata has been changed
@@ -676,62 +708,19 @@ function & p_get_renderer($mode) {
 /**
  * Gets the first heading from a file
  *
- * After P_GET_FIRST_HEADING_METADATA_LIMIT requests for different pages the title
- * index will be loaded and used instead. Use METADATA_DONT_RENDER when you are
- * requesting a lot of titles, METADATA_RENDER_USING_CACHE when you think
- * rendering the page although it hasn't changed might be needed (or also
- * want to influence rendering using events) and METADATA_RENDER_USING_SIMPLE_CACHE
- * otherwise. Use METADATA_RENDER_USING_CACHE with care as it could cause
- * parsing and rendering a lot of pages in one request.
- *
  * @param   string   $id       dokuwiki page id
  * @param   int      $render   rerender if first heading not known
  *                             default: METADATA_RENDER_USING_SIMPLE_CACHE
  *                             Possible values: METADATA_DONT_RENDER,
  *                                              METADATA_RENDER_USING_SIMPLE_CACHE,
- *                                              METADATA_RENDER_USING_CACHE
+ *                                              METADATA_RENDER_USING_CACHE,
+ *                                              METADATA_RENDER_UNLIMITED
  *
  * @author Andreas Gohr <andi@splitbrain.org>
  * @author Michael Hamann <michael@content-space.de>
  */
 function p_get_first_heading($id, $render=METADATA_RENDER_USING_SIMPLE_CACHE){
-    // counter how many titles have been requested using p_get_metadata
-    static $count = 1;
-    // the index of all titles, only loaded when many titles are requested
-    static $title_index = null;
-    // cache for titles requested using p_get_metadata
-    static $title_cache = array();
-
-    $id = cleanID($id);
-
-    // check if this title has already been requested
-    if (isset($title_cache[$id]))
-      return $title_cache[$id];
-
-    // check if already too many titles have been requested and probably
-    // using the title index is better
-    if ($count > P_GET_FIRST_HEADING_METADATA_LIMIT) {
-        if (is_null($title_index)) {
-            $pages  = array_map('rtrim', idx_getIndex('page', ''));
-            $titles = array_map('rtrim', idx_getIndex('title', ''));
-            // check for corrupt title index #FS2076
-            if(count($pages) != count($titles)){
-                $titles = array_fill(0,count($pages),'');
-                @unlink($conf['indexdir'].'/title.idx'); // will be rebuilt in inc/init.php
-            } else {
-                if (!empty($pages)) // array_combine throws a warning when the parameters are empty arrays
-                    $title_index = array_combine($pages, $titles);
-                else
-                    $title_index = array();
-            }
-        }
-        if (!empty($title_index)) // don't use the index when it obviously isn't working
-            return $title_index[$id];
-    }
-
-    ++$count;
-    $title_cache[$id] = p_get_metadata($id,'title',$render);
-    return $title_cache[$id];
+    return p_get_metadata(cleanID($id),'title',$render);
 }
 
 /**
diff --git a/inc/template.php b/inc/template.php
index e028fe39c7991847bef3f163c19e4bd4ccce6439..99ab8f35f10bcef8eada314b4a4d8710391a7d6c 100644
--- a/inc/template.php
+++ b/inc/template.php
@@ -155,7 +155,7 @@ function tpl_toc($return=false){
         $toc = $TOC;
     }elseif(($ACT == 'show' || substr($ACT,0,6) == 'export') && !$REV && $INFO['exists']){
         // get TOC from metadata, render if neccessary
-        $meta = p_get_metadata($ID, false, true);
+        $meta = p_get_metadata($ID, false, METADATA_RENDER_USING_CACHE);
         if(isset($meta['internal']['toc'])){
             $tocok = $meta['internal']['toc'];
         }else{