diff --git a/catalogue/SqliteCatalogue.cpp b/catalogue/SqliteCatalogue.cpp
index 4f1bc1690971de1c3fda0140431af602088c2019..0ccaa5836e1df0bc91ca6b07d3005c61f1552cdf 100644
--- a/catalogue/SqliteCatalogue.cpp
+++ b/catalogue/SqliteCatalogue.cpp
@@ -185,21 +185,31 @@ void SqliteCatalogue::deleteArchiveFile(const std::string &diskInstanceName, con
 //------------------------------------------------------------------------------
 uint64_t SqliteCatalogue::getNextArchiveFileId(rdbms::Conn &conn) {
   try {
-    conn.executeNonQuery("INSERT INTO ARCHIVE_FILE_ID VALUES(NULL)", rdbms::AutocommitMode::AUTOCOMMIT_ON);
+    // The SQLite implemenation of getNextArchiveFileId() serializes access to
+    // the SQLite database in order to avoid busy errors
+    threading::MutexLocker locker(m_mutex);
+
+    rdbms::AutoRollback autoRollback(conn);
+
+    conn.executeNonQuery("UPDATE ARCHIVE_FILE_ID SET ID = ID + 1", rdbms::AutocommitMode::AUTOCOMMIT_OFF);
     uint64_t archiveFileId = 0;
     {
-      const char *const sql = "SELECT LAST_INSERT_ROWID() AS ID";
+      const char *const sql =
+        "SELECT "
+           "ID AS ID "
+        "FROM "
+          "ARCHIVE_FILE_ID";
       auto stmt = conn.createStmt(sql);
-      auto rset = stmt.executeQuery(rdbms::AutocommitMode::AUTOCOMMIT_ON);
+      auto rset = stmt.executeQuery(rdbms::AutocommitMode::AUTOCOMMIT_OFF);
       if(!rset.next()) {
-        throw exception::Exception(std::string("Unexpected empty result set for '") + sql + "\'");
+        throw exception::Exception("ARCHIVE_FILE_ID table is empty");
       }
       archiveFileId = rset.columnUint64("ID");
       if(rset.next()) {
-        throw exception::Exception(std::string("Unexpectedly found more than one row in the result of '") + sql + "\'");
+        throw exception::Exception("Found more than one ID counter in the ARCHIVE_FILE_ID table");
       }
     }
-    conn.executeNonQuery("DELETE FROM ARCHIVE_FILE_ID", rdbms::AutocommitMode::AUTOCOMMIT_ON);
+    conn.commit();
 
     return archiveFileId;
   } catch(exception::UserError &) {
@@ -214,30 +224,33 @@ uint64_t SqliteCatalogue::getNextArchiveFileId(rdbms::Conn &conn) {
 // getNextStorageClassId
 //------------------------------------------------------------------------------
 uint64_t SqliteCatalogue::getNextStorageClassId(rdbms::Conn &conn) {
-  try {
-    conn.executeNonQuery("INSERT INTO STORAGE_CLASS_ID VALUES(NULL)", rdbms::AutocommitMode::AUTOCOMMIT_ON);
-    uint64_t storageClassId = 0;
-    {
-      const char *const sql = "SELECT LAST_INSERT_ROWID() AS ID";
-      auto stmt = conn.createStmt(sql);
-      auto rset = stmt.executeQuery(rdbms::AutocommitMode::AUTOCOMMIT_ON);
-      if(!rset.next()) {
-        throw exception::Exception(std::string("Unexpected empty result set for '") + sql + "\'");
-      }
-      storageClassId = rset.columnUint64("ID");
-      if(rset.next()) {
-        throw exception::Exception(std::string("Unexpectedly found more than one row in the result of '") + sql + "\'");
-      }
-    }
-    conn.executeNonQuery("DELETE FROM STORAGE_CLASS_ID", rdbms::AutocommitMode::AUTOCOMMIT_ON);
+  // The SQLite implemenation of getNextStorageClassId() serializes access to
+  // the SQLite database in order to avoid busy errors
+  threading::MutexLocker locker(m_mutex);
 
-    return storageClassId;
-  } catch(exception::UserError &) {
-    throw;
-  } catch(exception::Exception &ex) {
-    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
-    throw;
+  rdbms::AutoRollback autoRollback(conn);
+
+  conn.executeNonQuery("UPDATE STORAGE_CLASS_ID SET ID = ID + 1", rdbms::AutocommitMode::AUTOCOMMIT_OFF);
+  uint64_t storageClassId = 0;
+  {
+    const char *const sql =
+      "SELECT "
+        "ID AS ID "
+      "FROM "
+        "STORAGE_CLASS_ID";
+    auto stmt = conn.createStmt(sql);
+    auto rset = stmt.executeQuery(rdbms::AutocommitMode::AUTOCOMMIT_OFF);
+    if(!rset.next()) {
+      throw exception::Exception("STORAGE_CLASS_ID table is empty");
+    }
+    storageClassId = rset.columnUint64("ID");
+    if(rset.next()) {
+      throw exception::Exception("Found more than one ID counter in the STORAGE_CLASS_ID table");
+    }
   }
+  conn.commit();
+
+  return storageClassId;
 }
 
 //------------------------------------------------------------------------------
diff --git a/catalogue/sqlite_catalogue_schema_header.sql b/catalogue/sqlite_catalogue_schema_header.sql
index 58e697395870faa928cfb2c1894f0365d935980d..d4b8454715321e269d2f80666f369b0e62a3e37e 100644
--- a/catalogue/sqlite_catalogue_schema_header.sql
+++ b/catalogue/sqlite_catalogue_schema_header.sql
@@ -1,6 +1,10 @@
 CREATE TABLE ARCHIVE_FILE_ID(
-  ID INTEGER PRIMARY KEY AUTOINCREMENT
+  ID INTEGER,
+  CONSTRAINT ARCHIVE_FILE_ID_PK PRIMARY KEY(ID)
 );
+INSERT INTO ARCHIVE_FILE_ID(ID) VALUES(1);
 CREATE TABLE STORAGE_CLASS_ID(
-  ID INTEGER PRIMARY KEY AUTOINCREMENT
+  ID INTEGER,
+  CONSTRAINT STORAGE_CLASS_ID_PK PRIMARY KEY(ID)
 );
+INSERT INTO STORAGE_CLASS_ID(ID) VALUES(1);