diff --git a/plugins/agiledashboard/include/AgileDashboard/BacklogItem/SubBacklogItemProvider.class.php b/plugins/agiledashboard/include/AgileDashboard/BacklogItem/SubBacklogItemProvider.class.php
index f66a820..c3ef8c9 100644
--- a/plugins/agiledashboard/include/AgileDashboard/BacklogItem/SubBacklogItemProvider.class.php
+++ b/plugins/agiledashboard/include/AgileDashboard/BacklogItem/SubBacklogItemProvider.class.php
@@ -22,42 +22,62 @@
 /**
  * Returns all tasks id in a Release
  *
- * Example of planning configuration:
+ * It leverage on ArtifactLink information and will recrusively inspect the
+ * milestone links (from top to bottom) and keep all artifacts that belongs to
+ * the backlog tracker.
  *
- * Release  --------- Epic
- *    Sprint  --------- Story
- *                        Task
+ * This is the same type of algorithm than used in AgileDashboard_Milestone_Backlog_ArtifactsFinder
  */
 class AgileDashboard_BacklogItem_SubBacklogItemProvider {
 
-    /** @var AgileDashboard_BacklogItem_SubBacklogItemDao */
+    /** @var Tracker_ArtifactDao */
     private $dao;
 
-    /** @var AgileDashboard_Planning_ParentBacklogTrackerCollectionProvider */
-    private $provider;
+    /** @var Integer[] */
+    private $backlog_ids = array();
 
-    public function __construct(
-        AgileDashboard_BacklogItem_SubBacklogItemDao $dao,
-        AgileDashboard_Planning_ParentBacklogTrackerCollectionProvider $parent_backlog_tracker_collection_provider
-    ) {
-        $this->dao      = $dao;
-        $this->provider = $parent_backlog_tracker_collection_provider;
+    /** @var Integer[] */
+    private $inspected_ids = array();
+
+    public function __construct(Tracker_ArtifactDao $dao) {
+        $this->dao = $dao;
     }
 
+    /**
+     * Return all indexed ids of artifacts linked on milestone that belong to backlog tracker
+     *
+     * @param Planning_Milestone $milestone
+     * @param Tracker $backlog_tracker
+     * @return array
+     */
     public function getMatchingIds(Planning_Milestone $milestone, Tracker $backlog_tracker) {
-        $milestone_id               = $milestone->getArtifactId();
-        $parent_backlog_trackers    = $this->provider->getParentBacklogTrackerCollection($backlog_tracker, $milestone);
-        $parent_backlog_tracker_ids = array_map(array($this, 'extractTrackerId'), $parent_backlog_trackers);
+        $milestone_id_seed = array($milestone->getArtifactId());
 
-        $row = $this->dao->getAllBacklogItemIdInMilestone($milestone_id, $parent_backlog_tracker_ids)->getRow();
-        if (! $row['list_of_ids']) {
-            return array();
-        }
+        $this->inspected_ids = $milestone_id_seed;
+        $this->filterBacklogIds($backlog_tracker->getId(), $milestone_id_seed);
 
-        return array_flip(explode(',', $row['list_of_ids']));
+        return $this->backlog_ids;
     }
 
-    private function extractTrackerId(Tracker $tracker) {
-        return $tracker->getId();
+    /**
+     * Retrieve all linked artifacts and keep only those that belong to backlog tracker
+     *
+     * We need to keep list of ids we already looked at so we avoid cycles.
+     *
+     * @param int $backlog_tracker_id
+     * @param array $artifacts
+     */
+    private function filterBacklogIds($backlog_tracker_id, array $artifacts) {
+        $artifacts_to_inspect = array();
+        foreach ($this->dao->getLinkedArtifactsByIds($artifacts, $this->inspected_ids) as $artifact_row) {
+            $artifacts_to_inspect[] = $artifact_row['id'];
+            if ($artifact_row['tracker_id'] == $backlog_tracker_id) {
+                $this->backlog_ids[$artifact_row['id']] = true;
+            }
+            $this->inspected_ids[] = $artifact_row['id'];
+        }
+        if (count($artifacts_to_inspect) > 0) {
+            $this->filterBacklogIds($backlog_tracker_id, $artifacts_to_inspect);
+        }
     }
-}
\ No newline at end of file
+}
diff --git a/plugins/agiledashboard/include/AgileDashboard/BacklogItemDao.class.php b/plugins/agiledashboard/include/AgileDashboard/BacklogItemDao.class.php
index 75098aa..346ef82 100644
--- a/plugins/agiledashboard/include/AgileDashboard/BacklogItemDao.class.php
+++ b/plugins/agiledashboard/include/AgileDashboard/BacklogItemDao.class.php
@@ -43,20 +43,6 @@ class AgileDashboard_BacklogItemDao extends DataAccessObject {
         return $this->retrieve($sql);
     }
 
-    public function getLinkedArtifacts($milestone_artifact_id) {
-        $milestone_artifact_id = $this->da->escapeInt($milestone_artifact_id);
-        $sql = "SELECT child_art.*
-                FROM tracker_artifact parent_art
-                    INNER JOIN tracker_field                        f          ON (f.tracker_id = parent_art.tracker_id AND f.formElement_type = 'art_link' AND use_it = 1)
-                    INNER JOIN tracker_changeset_value              cv         ON (cv.changeset_id = parent_art.last_changeset_id AND cv.field_id = f.id)
-                    INNER JOIN tracker_changeset_value_artifactlink artlink    ON (artlink.changeset_value_id = cv.id)
-                    INNER JOIN tracker_artifact                     child_art  ON (child_art.id = artlink.artifact_id)
-                WHERE parent_art.id = $milestone_artifact_id";
-
-
-        return $this->retrieve($sql);
-    }
-
     public function getTopBacklogArtifacts(array $milestone_tracker_ids) {
         $milestone_tracker_ids = $this->da->escapeIntImplode($milestone_tracker_ids);
 
diff --git a/plugins/agiledashboard/include/AgileDashboard/Milestone/Backlog/BacklogStrategyFactory.class.php b/plugins/agiledashboard/include/AgileDashboard/Milestone/Backlog/BacklogStrategyFactory.class.php
index 92b19d4..9eef047 100644
--- a/plugins/agiledashboard/include/AgileDashboard/Milestone/Backlog/BacklogStrategyFactory.class.php
+++ b/plugins/agiledashboard/include/AgileDashboard/Milestone/Backlog/BacklogStrategyFactory.class.php
@@ -92,9 +92,7 @@ class AgileDashboard_Milestone_Backlog_BacklogStrategyFactory {
                 ->instanciateWith(array($this->artifact_factory, 'getInstanceFromRow'));
         }
 
-        return $this->dao
-                ->getLinkedArtifacts($milestone->getArtifactId())
-                ->instanciateWith(array($this->artifact_factory, 'getInstanceFromRow'));
+        return $this->artifact_factory->getLinkedArtifacts($milestone->getArtifact());
     }
 }
 ?>
diff --git a/plugins/agiledashboard/include/AgileDashboard/Planning/ParentBacklogTrackerCollectionProvider.class.php b/plugins/agiledashboard/include/AgileDashboard/Planning/ParentBacklogTrackerCollectionProvider.class.php
deleted file mode 100644
index 54290ce..0000000
--- a/plugins/agiledashboard/include/AgileDashboard/Planning/ParentBacklogTrackerCollectionProvider.class.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-/**
- * Copyright (c) Enalean, 2013. All Rights Reserved.
- *
- * This file is a part of Tuleap.
- *
- * Tuleap is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Tuleap is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tuleap. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * I return a collection of backlog tracker, parent of a given tracker,
- * until I matches a planning for teh given milestone
- *
- * Example of planning configuration:
- *
- *                  Theme
- * Release  --------- Epic
- *    Sprint  --------- Story
- *                        Task
- *                          TestCase
- *
- * For the milestone "release 6.2" and the backlog tracker "task", the collection
- * will be ["epic", "story", "task"]
- */
-class AgileDashboard_Planning_ParentBacklogTrackerCollectionProvider {
-
-    /** @return Tracker[] */
-    public function getParentBacklogTrackerCollection(Tracker $backlog_tracker, Planning_Milestone $milestone) {
-        $trackers                  = array($backlog_tracker);
-        $milestone_backlog_tracker_ids = $milestone->getPlanning()->getBacklogTrackersIds();
-        $current_backlog_tracker   = $backlog_tracker;
-        if (in_array($current_backlog_tracker->getId(), $milestone_backlog_tracker_ids)) {
-            return array($current_backlog_tracker);
-        }
-
-        while (($parent = $current_backlog_tracker->getParent()) && ! in_array($parent->getId(), $milestone_backlog_tracker_ids)) {
-            $trackers[] = $parent;
-            $current_backlog_tracker = $parent;
-        }
-        if (! $parent) {
-            return array();
-        }
-        if (in_array($parent->getId(), $milestone_backlog_tracker_ids)) {
-            $trackers[] = $parent;
-        }
-
-        return array_reverse($trackers);
-    }
-}
diff --git a/plugins/agiledashboard/include/agiledashboardPlugin.class.php b/plugins/agiledashboard/include/agiledashboardPlugin.class.php
index 4d238fe..76f50cf 100644
--- a/plugins/agiledashboard/include/agiledashboardPlugin.class.php
+++ b/plugins/agiledashboard/include/agiledashboardPlugin.class.php
@@ -120,24 +120,17 @@ class AgileDashboardPlugin extends Plugin {
         $backlog_tracker = $params['tracker'];
 
         $milestone_id_provider = new AgileDashboard_Milestone_SelectedMilestoneIdProvider($params['additional_criteria']);
-        $milestone_id = $milestone_id_provider->getMilestoneId();
-        if (! $milestone_id) {
-            return;
-        }
-
-        $provider = new AgileDashboard_BacklogItem_SubBacklogItemProvider(
-            new AgileDashboard_BacklogItem_SubBacklogItemDao(),
-            new AgileDashboard_Planning_ParentBacklogTrackerCollectionProvider()
+        $milestone_id          = $milestone_id_provider->getMilestoneId();
+        $milestone             = $this->getMilestoneFactory()->getBareMilestoneByArtifactId(
+            UserManager::instance()->getCurrentUser(),
+            $milestone_id
         );
-        $artifact = Tracker_ArtifactFactory::instance()->getArtifactById($milestone_id);
 
-        if (! $artifact) {
-            return;
+        if ($milestone) {
+            $provider = new AgileDashboard_BacklogItem_SubBacklogItemProvider(new Tracker_ArtifactDao());
+            $params['result'][]         = $provider->getMatchingIds($milestone, $backlog_tracker);
+            $params['search_performed'] = true;
         }
-
-        $milestone                  = $this->getMilestoneFactory()->getMilestoneFromArtifact($artifact);
-        $params['result'][]         = $provider->getMatchingIds($milestone, $backlog_tracker);
-        $params['search_performed'] = true;
     }
 
     /**
diff --git a/plugins/agiledashboard/tests/include/AgileDashboard/BacklogItem/SubBacklogItemProviderTest.php b/plugins/agiledashboard/tests/include/AgileDashboard/BacklogItem/SubBacklogItemProviderTest.php
index 040936e..c8c506f 100644
--- a/plugins/agiledashboard/tests/include/AgileDashboard/BacklogItem/SubBacklogItemProviderTest.php
+++ b/plugins/agiledashboard/tests/include/AgileDashboard/BacklogItem/SubBacklogItemProviderTest.php
@@ -26,35 +26,26 @@ class AgileDashboard_BacklogItem_SubBacklogItemProviderTest extends TuleapTestCa
     public function setUp() {
         parent::setUp();
         $this->milestone       = aMilestone()->withArtifact(anArtifact()->withId(3)->build())->build();
-        $this->backlog_tracker = aTracker()->build();
-        $this->dao             = mock('AgileDashboard_BacklogItem_SubBacklogItemDao');
-
-        $this->epic_tracker  = aTracker()->withId(25)->build();
-        $this->story_tracker = aTracker()->withId(29)->build();
-        $this->task_tracker  = aTracker()->withId(28)->build();
-        $this->parent_backlog_tracker_collection_provider = mock('AgileDashboard_Planning_ParentBacklogTrackerCollectionProvider');
-        stub($this->parent_backlog_tracker_collection_provider)
-            ->getParentBacklogTrackerCollection($this->backlog_tracker, $this->milestone)
-            ->returns(array($this->epic_tracker, $this->story_tracker, $this->task_tracker));
-
-        $this->provider = new AgileDashboard_BacklogItem_SubBacklogItemProvider(
-            $this->dao,
-            $this->parent_backlog_tracker_collection_provider
-        );
+        $this->backlog_tracker = aTracker()->withId(35)->build();
+        $this->dao             = mock('Tracker_ArtifactDao');
+
+        $this->provider = new AgileDashboard_BacklogItem_SubBacklogItemProvider($this->dao);
     }
+
     public function itReturnsTheMatchingIds() {
-        stub($this->dao)->getAllBacklogItemIdInMilestone(3, array(25,29,28))->returnsDar(
-            array('list_of_ids' => '7,8,11')
+        stub($this->dao)->getLinkedArtifactsByIds(array(3), array(3))->returnsDar(
+            array('id' => 7,  'tracker_id' => 35),
+            array('id' => 8,  'tracker_id' => 35),
+            array('id' => 11, 'tracker_id' => 35)
         );
+        stub($this->dao)->getLinkedArtifactsByIds(array(7, 8, 11), array(3, 7, 8, 11))->returnsEmptyDar();
 
         $result = $this->provider->getMatchingIds($this->milestone, $this->backlog_tracker);
         $this->assertEqual(array_keys($result), array(7, 8, 11));
     }
 
     public function itReturnsAnEmptyResultIfThereIsNoMatchingId() {
-        stub($this->dao)->getAllBacklogItemIdInMilestone(3, array(25,29,28))->returnsDar(
-            array('list_of_ids' => NULL)
-        );
+        stub($this->dao)->getLinkedArtifactsByIds()->returnsEmptyDar();
 
         $result = $this->provider->getMatchingIds($this->milestone, $this->backlog_tracker);
         $this->assertEqual($result, array());
diff --git a/plugins/agiledashboard/tests/include/AgileDashboard/Planning/ParentBacklogTrackerCollectionProviderTest.php b/plugins/agiledashboard/tests/include/AgileDashboard/Planning/ParentBacklogTrackerCollectionProviderTest.php
deleted file mode 100644
index e60905e..0000000
--- a/plugins/agiledashboard/tests/include/AgileDashboard/Planning/ParentBacklogTrackerCollectionProviderTest.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-/**
- * Copyright (c) Enalean, 2012. All Rights Reserved.
- *
- * This file is a part of Tuleap.
- *
- * Tuleap is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Tuleap is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tuleap. If not, see <http://www.gnu.org/licenses/>.
- */
-require_once dirname(__FILE__).'/../../../bootstrap.php';
-
-class AgileDashboard_Planning_ParentBacklogTrackerCollectionProviderTest extends TuleapTestCase {
-
-
-    public function setUp() {
-        /*
-                        Theme
-        Release  ------- Epic
-          Sprint -------  Story
-                           Task
-                            TestCase
-        */
-        $this->theme_tracker   = aTracker()->withId('theme')->withParent(null)->build();
-        $this->epic_tracker    = aTracker()->withId('epic')->withParent($this->theme_tracker)->build();
-        $this->story_tracker   = aTracker()->withId('story')->withParent($this->epic_tracker)->build();
-        $this->task_tracker    = aTracker()->withId('task')->withParent($this->story_tracker)->build();
-        $this->test_tracker    = aTracker()->withId('test')->withParent($this->story_tracker)->build();
-        $this->release_tracker = aTracker()->withId('release')->withParent(null)->build();
-        $this->sprint_tracker  = aTracker()->withId('sprint')->withParent($this->epic_tracker)->build();
-
-        $release_planning = aPlanning()
-            ->withPlanningTracker($this->release_tracker)
-            ->withBacklogTracker($this->epic_tracker)
-            ->build();
-
-        $this->milestone_release = aMilestone()->withPlanning($release_planning)->build();
-
-        $this->provider = new AgileDashboard_Planning_ParentBacklogTrackerCollectionProvider();
-    }
-
-    public function itReturnsEmptyArrayWhenNoMatch() {
-        $dummy_milestone = aMilestone()
-            ->withPlanning(
-                aPlanning()->withBacklogTracker($this->test_tracker)->build()
-            )->build();
-
-        $this->assertEqual(
-            $this->provider->getParentBacklogTrackerCollection($this->task_tracker, $dummy_milestone),
-            array()
-        );
-    }
-
-    public function itReturnsEpicStoryAndTaskWhenBacklogTrackerIsTask() {
-        $this->assertEqual(
-            $this->provider->getParentBacklogTrackerCollection($this->task_tracker, $this->milestone_release),
-            array($this->epic_tracker, $this->story_tracker, $this->task_tracker)
-        );
-    }
-
-    public function itReturnsEpicAndStoryWhenBacklogTrackerIsStory() {
-        $this->assertEqual(
-            $this->provider->getParentBacklogTrackerCollection($this->story_tracker, $this->milestone_release),
-            array($this->epic_tracker, $this->story_tracker)
-        );
-    }
-
-    public function itReturnsEpicWhenBacklogTrackerIsEpic() {
-        $this->assertEqual(
-            $this->provider->getParentBacklogTrackerCollection($this->epic_tracker, $this->milestone_release),
-            array($this->epic_tracker)
-        );
-    }
-}
diff --git a/plugins/tracker/include/Tracker/Artifact/Tracker_ArtifactFactory.class.php b/plugins/tracker/include/Tracker/Artifact/Tracker_ArtifactFactory.class.php
index 7830c08..55d1289 100644
--- a/plugins/tracker/include/Tracker/Artifact/Tracker_ArtifactFactory.class.php
+++ b/plugins/tracker/include/Tracker/Artifact/Tracker_ArtifactFactory.class.php
@@ -343,6 +343,13 @@ class Tracker_ArtifactFactory {
     /**
      * @return Tracker_Artifact[]
      */
+    public function getLinkedArtifacts(Tracker_Artifact $artifact) {
+        return $this->getDao()->getLinkedArtifacts($artifact->getId())->instanciateWith(array($this, 'getInstanceFromRow'));
+    }
+
+    /**
+     * @return Tracker_Artifact[]
+     */
     public function getChildren(Tracker_Artifact $artifact) {
         return $this->getDao()->getChildren($artifact->getId())->instanciateWith(array($this, 'getInstanceFromRow'));
     }
diff --git a/plugins/tracker/include/Tracker/Artifact/dao/Tracker_ArtifactDao.class.php b/plugins/tracker/include/Tracker/Artifact/dao/Tracker_ArtifactDao.class.php
index 324072e..861f687 100644
--- a/plugins/tracker/include/Tracker/Artifact/dao/Tracker_ArtifactDao.class.php
+++ b/plugins/tracker/include/Tracker/Artifact/dao/Tracker_ArtifactDao.class.php
@@ -507,6 +507,40 @@ class Tracker_ArtifactDao extends DataAccessObject {
         return $this->retrieve($sql);
     }
 
+    /**
+     * Retrieve all artifacts linked by the given one
+     *
+     * @param Integer $artifact_id
+     * @return DataAccessResult
+     */
+    public function getLinkedArtifacts($artifact_id) {
+        return $this->getLinkedArtifactsByIds(array($artifact_id));
+    }
+
+    /**
+     * Return all artifacts linked by the given artifact (possible exclusion)
+     *
+     * @param array $artifact_ids Artifact ids to inspect
+     * @param array $excluded_ids Exclude those ids from the results
+     * @return DataAccessResult
+     */
+    public function getLinkedArtifactsByIds(array $artifact_ids, array $excluded_ids = array()) {
+        $artifact_ids = $this->da->escapeIntImplode($artifact_ids);
+        $exclude      = '';
+        if (count($excluded_ids) > 0) {
+            $exclude = 'AND linked_art.id NOT IN ('.$this->da->escapeIntImplode($excluded_ids).')';
+        }
+        $sql = "SELECT linked_art.*
+                FROM tracker_artifact parent_art
+                    INNER JOIN tracker_field                        f          ON (f.tracker_id = parent_art.tracker_id AND f.formElement_type = 'art_link' AND use_it = 1)
+                    INNER JOIN tracker_changeset_value              cv         ON (cv.changeset_id = parent_art.last_changeset_id AND cv.field_id = f.id)
+                    INNER JOIN tracker_changeset_value_artifactlink artlink    ON (artlink.changeset_value_id = cv.id)
+                    INNER JOIN tracker_artifact                     linked_art ON (linked_art.id = artlink.artifact_id $exclude)
+                WHERE parent_art.id IN ($artifact_ids)";
+
+        return $this->retrieve($sql);
+    }
+
     /** @return array */
     public function getIdsSortedByPriority(array $artifact_ids) {
         $artifact_ids = $this->da->escapeIntImplode($artifact_ids);
