diff --git a/database.go b/database.go
index 47b4bb821740350edbf7d7cd9f76e649b0b01ac4..9e004992a350ec3aa4b7895e4206322c7b7b6646 100644
--- a/database.go
+++ b/database.go
@@ -50,9 +50,22 @@ func (id BookId) String() string {
 }
 
 func (id BookId) Key() []byte {
-	var buf bytes.Buffer
-	binary.Write(&buf, binary.LittleEndian, id)
-	return buf.Bytes()
+	var b [8]byte
+	binary.LittleEndian.PutUint64(b[:], uint64(id))
+	return b[:]
+}
+
+func NewID() BookId {
+	return BookId(rand.Int63())
+}
+
+func ParseID(s string) BookId {
+	id, _ := strconv.ParseUint(s, 10, 64)
+	return BookId(id)
+}
+
+func ParseBinaryID(b []byte) BookId {
+	return BookId(binary.LittleEndian.Uint64(b))
 }
 
 type Book struct {
@@ -85,15 +98,6 @@ func init() {
 	rand.Seed(seed)
 }
 
-func NewID() BookId {
-	return BookId(rand.Int63())
-}
-
-func ParseID(s string) BookId {
-	id, _ := strconv.ParseUint(s, 10, 64)
-	return BookId(id)
-}
-
 // The structure that gets actually indexed.
 type flatBook struct {
 	Title       string   `json:"title"`
@@ -251,6 +255,42 @@ func (db *Database) setupIndex(path string) error {
 	return nil
 }
 
+var schemaVersionKey = []byte("_liber_schema_version")
+
+func (db *Database) getSchemaVersion() uint64 {
+	data, err := db.ldb.Get(schemaVersionKey, nil)
+	if err != nil {
+		return 0
+	}
+	return binary.LittleEndian.Uint64(data)
+}
+
+func (db *Database) setSchemaVersion(v uint64) {
+	var b [8]byte
+	binary.LittleEndian.PutUint64(b[:], v)
+	db.ldb.Put(schemaVersionKey, b[:], nil)
+}
+
+type databaseMigration struct {
+	version uint64
+	run     func(db *Database) error
+}
+
+func (db *Database) runMigrations(migrations []databaseMigration) error {
+	version := db.getSchemaVersion()
+	for _, m := range migrations {
+		if m.version < version {
+			continue
+		}
+		if err := m.run(db); err != nil {
+			return err
+		}
+		version = m.version
+		db.setSchemaVersion(version)
+	}
+	return nil
+}
+
 func (db *Database) Close() {
 	db.index.Close()
 	db.ldb.Close()
@@ -570,10 +610,7 @@ func keyToId(key []byte) BookId {
 	if n < 0 {
 		return 0
 	}
-
-	var id uint64
-	binary.Read(bytes.NewReader(key[n+1:]), binary.LittleEndian, &id)
-	return BookId(id)
+	return ParseBinaryID(key[n+1:])
 }
 
 func keyRange(prefix []byte) ([]byte, []byte) {