diff --git a/src/cmds/restic/cmd_find.go b/src/cmds/restic/cmd_find.go
index 24258d510..683adaa87 100644
--- a/src/cmds/restic/cmd_find.go
+++ b/src/cmds/restic/cmd_find.go
@@ -61,7 +61,7 @@ func parseTime(str string) (time.Time, error) {
 
 func (c CmdFind) findInTree(repo *repository.Repository, id restic.ID, path string) ([]findResult, error) {
 	debug.Log("restic.find", "checking tree %v\n", id)
-	tree, err := restic.LoadTree(repo, id)
+	tree, err := repo.LoadTree(id)
 	if err != nil {
 		return nil, err
 	}
diff --git a/src/cmds/restic/cmd_ls.go b/src/cmds/restic/cmd_ls.go
index 733f424b6..4e3b29e8a 100644
--- a/src/cmds/restic/cmd_ls.go
+++ b/src/cmds/restic/cmd_ls.go
@@ -47,7 +47,7 @@ func (cmd CmdLs) printNode(prefix string, n *restic.Node) string {
 }
 
 func (cmd CmdLs) printTree(prefix string, repo *repository.Repository, id restic.ID) error {
-	tree, err := restic.LoadTree(repo, id)
+	tree, err := repo.LoadTree(id)
 	if err != nil {
 		return err
 	}
diff --git a/src/restic/archiver/archive_reader_test.go b/src/restic/archiver/archive_reader_test.go
index da46f030a..b402bc6d1 100644
--- a/src/restic/archiver/archive_reader_test.go
+++ b/src/restic/archiver/archive_reader_test.go
@@ -21,7 +21,7 @@ func loadBlob(t *testing.T, repo *repository.Repository, id restic.ID, buf []byt
 }
 
 func checkSavedFile(t *testing.T, repo *repository.Repository, treeID restic.ID, name string, rd io.Reader) {
-	tree, err := restic.LoadTree(repo, treeID)
+	tree, err := repo.LoadTree(treeID)
 	if err != nil {
 		t.Fatalf("LoadTree() returned error %v", err)
 	}
diff --git a/src/restic/checker/checker.go b/src/restic/checker/checker.go
index 88a8eec8e..df879fdfd 100644
--- a/src/restic/checker/checker.go
+++ b/src/restic/checker/checker.go
@@ -376,7 +376,7 @@ func loadTreeWorker(repo restic.Repository,
 			}
 			debug.Log("checker.loadTreeWorker", "load tree %v", treeID.Str())
 
-			tree, err := restic.LoadTree(repo, treeID)
+			tree, err := repo.LoadTree(treeID)
 			debug.Log("checker.loadTreeWorker", "load tree %v (%v) returned err: %v", tree, treeID.Str(), err)
 			job = treeJob{ID: treeID, error: err, Tree: tree}
 			outCh = out
diff --git a/src/restic/find.go b/src/restic/find.go
index bfcdbb58f..dcc9d0251 100644
--- a/src/restic/find.go
+++ b/src/restic/find.go
@@ -6,7 +6,7 @@ package restic
 func FindUsedBlobs(repo Repository, treeID ID, blobs BlobSet, seen BlobSet) error {
 	blobs.Insert(BlobHandle{ID: treeID, Type: TreeBlob})
 
-	tree, err := LoadTree(repo, treeID)
+	tree, err := repo.LoadTree(treeID)
 	if err != nil {
 		return err
 	}
diff --git a/src/restic/fuse/dir.go b/src/restic/fuse/dir.go
index a89617e5f..14f8c7f21 100644
--- a/src/restic/fuse/dir.go
+++ b/src/restic/fuse/dir.go
@@ -29,7 +29,7 @@ type dir struct {
 
 func newDir(repo *repository.Repository, node *restic.Node, ownerIsRoot bool) (*dir, error) {
 	debug.Log("newDir", "new dir for %v (%v)", node.Name, node.Subtree.Str())
-	tree, err := restic.LoadTree(repo, *node.Subtree)
+	tree, err := repo.LoadTree(*node.Subtree)
 	if err != nil {
 		debug.Log("newDir", "  error loading tree %v: %v", node.Subtree.Str(), err)
 		return nil, err
@@ -59,7 +59,7 @@ func replaceSpecialNodes(repo *repository.Repository, node *restic.Node) ([]*res
 		return []*restic.Node{node}, nil
 	}
 
-	tree, err := restic.LoadTree(repo, *node.Subtree)
+	tree, err := repo.LoadTree(*node.Subtree)
 	if err != nil {
 		return nil, err
 	}
@@ -69,7 +69,7 @@ func replaceSpecialNodes(repo *repository.Repository, node *restic.Node) ([]*res
 
 func newDirFromSnapshot(repo *repository.Repository, snapshot SnapshotWithId, ownerIsRoot bool) (*dir, error) {
 	debug.Log("newDirFromSnapshot", "new dir for snapshot %v (%v)", snapshot.ID.Str(), snapshot.Tree.Str())
-	tree, err := restic.LoadTree(repo, *snapshot.Tree)
+	tree, err := repo.LoadTree(*snapshot.Tree)
 	if err != nil {
 		debug.Log("newDirFromSnapshot", "  loadTree(%v) failed: %v", snapshot.ID.Str(), err)
 		return nil, err
diff --git a/src/restic/node.go b/src/restic/node.go
index 427ed6303..c4cff8ca5 100644
--- a/src/restic/node.go
+++ b/src/restic/node.go
@@ -218,10 +218,11 @@ func (node Node) createFileAt(path string, repo Repository) error {
 			buf = make([]byte, size)
 		}
 
-		buf, err := repo.LoadBlob(id, DataBlob, buf)
+		n, err := repo.LoadDataBlob(id, buf)
 		if err != nil {
 			return err
 		}
+		buf = buf[:n]
 
 		_, err = f.Write(buf)
 		if err != nil {
diff --git a/src/restic/repository.go b/src/restic/repository.go
index c0567ec98..5c1067f7b 100644
--- a/src/restic/repository.go
+++ b/src/restic/repository.go
@@ -31,10 +31,11 @@ type Repository interface {
 	SaveAndEncrypt(BlobType, []byte, *ID) (ID, error)
 	SaveJSONUnpacked(FileType, interface{}) (ID, error)
 
-	LoadJSONPack(BlobType, ID, interface{}) error
 	LoadJSONUnpacked(FileType, ID, interface{}) error
-	LoadBlob(ID, BlobType, []byte) ([]byte, error)
 	LoadAndDecrypt(FileType, ID) ([]byte, error)
+
+	LoadTree(id ID) (*Tree, error)
+	LoadDataBlob(id ID, buf []byte) (int, error)
 }
 
 // Deleter removes all data stored in a backend/repo.
diff --git a/src/restic/repository/repository.go b/src/restic/repository/repository.go
index a400b85e3..87025425d 100644
--- a/src/restic/repository/repository.go
+++ b/src/restic/repository/repository.go
@@ -589,3 +589,45 @@ func (r *Repository) Delete() error {
 func (r *Repository) Close() error {
 	return r.be.Close()
 }
+
+// LoadTree loads a tree from the repository.
+func (r *Repository) LoadTree(id restic.ID) (*restic.Tree, error) {
+	size, err := r.idx.LookupSize(id, restic.TreeBlob)
+	if err != nil {
+		return nil, err
+	}
+
+	buf := make([]byte, size)
+
+	buf, err = r.LoadBlob(id, restic.TreeBlob, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	t := &restic.Tree{}
+	err = json.Unmarshal(buf, t)
+	if err != nil {
+		return nil, err
+	}
+
+	return t, nil
+}
+
+// LoadDataBlob loads a data blob from the repository to the buffer.
+func (r *Repository) LoadDataBlob(id restic.ID, buf []byte) (int, error) {
+	size, err := r.idx.LookupSize(id, restic.DataBlob)
+	if err != nil {
+		return 0, err
+	}
+
+	if len(buf) < int(size) {
+		return 0, errors.Errorf("buffer is too small for data blob (%d < %d)", len(buf), size)
+	}
+
+	buf, err = r.LoadBlob(id, restic.DataBlob, buf)
+	if err != nil {
+		return 0, err
+	}
+
+	return len(buf), err
+}
diff --git a/src/restic/restorer.go b/src/restic/restorer.go
index 7ea7f0123..e3fceb67f 100644
--- a/src/restic/restorer.go
+++ b/src/restic/restorer.go
@@ -39,7 +39,7 @@ func NewRestorer(repo Repository, id ID) (*Restorer, error) {
 }
 
 func (res *Restorer) restoreTo(dst string, dir string, treeID ID) error {
-	tree, err := LoadTree(res.repo, treeID)
+	tree, err := res.repo.LoadTree(treeID)
 	if err != nil {
 		return res.Error(dir, nil, err)
 	}
diff --git a/src/restic/tree.go b/src/restic/tree.go
index f27393fa8..f2c1c04a9 100644
--- a/src/restic/tree.go
+++ b/src/restic/tree.go
@@ -25,20 +25,6 @@ func (t Tree) String() string {
 	return fmt.Sprintf("Tree<%d nodes>", len(t.Nodes))
 }
 
-type TreeLoader interface {
-	LoadJSONPack(BlobType, ID, interface{}) error
-}
-
-func LoadTree(repo TreeLoader, id ID) (*Tree, error) {
-	tree := &Tree{}
-	err := repo.LoadJSONPack(TreeBlob, id, tree)
-	if err != nil {
-		return nil, err
-	}
-
-	return tree, nil
-}
-
 // Equals returns true if t and other have exactly the same nodes.
 func (t Tree) Equals(other *Tree) bool {
 	if len(t.Nodes) != len(other.Nodes) {
@@ -85,6 +71,7 @@ func (t Tree) binarySearch(name string) (int, *Node, error) {
 	return pos, nil, errors.New("named node not found")
 }
 
+// Find returns a node with the given name.
 func (t Tree) Find(name string) (*Node, error) {
 	_, node, err := t.binarySearch(name)
 	return node, err
diff --git a/src/restic/tree_test.go b/src/restic/tree_test.go
index f8d632df9..3c581ec68 100644
--- a/src/restic/tree_test.go
+++ b/src/restic/tree_test.go
@@ -104,7 +104,7 @@ func TestLoadTree(t *testing.T) {
 	OK(t, repo.Flush())
 
 	// load tree again
-	tree2, err := restic.LoadTree(repo, id)
+	tree2, err := repo.LoadTree(id)
 	OK(t, err)
 
 	Assert(t, tree.Equals(tree2),
diff --git a/src/restic/walk/walk.go b/src/restic/walk/walk.go
index 456c2b9be..fbe322f63 100644
--- a/src/restic/walk/walk.go
+++ b/src/restic/walk/walk.go
@@ -156,17 +156,21 @@ func loadTreeWorker(wg *sync.WaitGroup, in <-chan loadTreeJob, load treeLoader,
 	}
 }
 
+// TreeLoader loads tree objects.
+type TreeLoader interface {
+	LoadTree(restic.ID) (*restic.Tree, error)
+}
+
 const loadTreeWorkers = 10
 
 // Tree walks the tree specified by id recursively and sends a job for each
 // file and directory it finds. When the channel done is closed, processing
 // stops.
-func Tree(repo restic.TreeLoader, id restic.ID, done chan struct{}, jobCh chan<- TreeJob) {
+func Tree(repo TreeLoader, id restic.ID, done chan struct{}, jobCh chan<- TreeJob) {
 	debug.Log("WalkTree", "start on %v, start workers", id.Str())
 
 	load := func(id restic.ID) (*restic.Tree, error) {
-		tree := &restic.Tree{}
-		err := repo.LoadJSONPack(restic.TreeBlob, id, tree)
+		tree, err := repo.LoadTree(id)
 		if err != nil {
 			return nil, err
 		}
diff --git a/src/restic/walk/walk_test.go b/src/restic/walk/walk_test.go
index 1a33c0ca0..221f5df9c 100644
--- a/src/restic/walk/walk_test.go
+++ b/src/restic/walk/walk_test.go
@@ -95,9 +95,9 @@ type delayRepo struct {
 	delay time.Duration
 }
 
-func (d delayRepo) LoadJSONPack(t restic.BlobType, id restic.ID, dst interface{}) error {
+func (d delayRepo) LoadTree(id restic.ID) (*restic.Tree, error) {
 	time.Sleep(d.delay)
-	return d.repo.LoadJSONPack(t, id, dst)
+	return d.repo.LoadTree(id)
 }
 
 var repoFixture = filepath.Join("testdata", "walktree-test-repo.tar.gz")