diff --git a/inc/lektor/database.h b/inc/lektor/database.h
index afeb3466582317adb50a478896eeb20a0831f3a6..b12c6d85a30d0e53073effa7417da0ac22a624bd 100644
--- a/inc/lektor/database.h
+++ b/inc/lektor/database.h
@@ -103,6 +103,14 @@ bool database_queue_shuffle(lkt_db *db);
 bool database_queue_seekid (lkt_db *db, int id, int *out_pos);
 bool database_queue_dump   (lkt_db *db, const char *plt_name);
 
+/* Add multiple IDs at once to the queue. The `int *` is the pointy thing that
+ * STB returns to you. Be warned that all the queries will be done 10 per 10,
+ * so if you do an add with 100 items, it will do 10 requests.
+ * The function returns `true` if the adds where successfull, `false` if any
+ * error occured.
+ * TODO: Add a way to manually set the step count. */
+bool database_queue_multi_add_id(lkt_db *, size_t *ids_stb_list, int priority);
+
 /* Control the playing state of the queue. */
 bool database_queue_toggle_pause(lkt_db *db);
 bool database_queue_play        (lkt_db *db, int pos);
diff --git a/src/database/queue.c b/src/database/queue.c
index 37752828f019a3b129ce90e9e64809b46f71e5d4..7597775e5fe0246319b5c8fca4c25eca3dd68653 100644
--- a/src/database/queue.c
+++ b/src/database/queue.c
@@ -1,6 +1,7 @@
 #include <lektor/common.h>
 #include <lektor/database.h>
 #include <lektor/internal/dbmacro.h>
+#include <lektor/stb/ds.h>
 
 #define sqlite_just_exec(func, query)                                 \
     bool func(lkt_db *db)                                             \
@@ -1089,3 +1090,67 @@ error:
     sqlite3_finalize(stmt);
     return ret;
 }
+
+bool
+database_queue_multi_add_id(lkt_db *db, size_t *ids, int priority)
+{
+    if (ids == NULL) {
+        LOG_ERROR("DB", "Can't add a list of IDs to the queue when the list's pointer is NULL");
+        return false;
+    }
+    if ((priority < 1) || (priority > 5)) {
+        LOG_ERROR("DB", "The priority must be between 1 and 5, here it is %d", priority);
+        return false;
+    }
+
+    static const int ADD_STEP = 10; /* TODO: Let the user specify that thing */
+    static const char *SQL_STMT_TEMPLATE =
+        "INSERT INTO queue (kara_id, priority)"
+        " SELECT kara.id, %d"              /* The priority */
+        " FROM kara WHERE kara.id IN (%s)" /* The list of ids, comma-separated */
+        ";";
+
+    const size_t ids_len = arrlenu(ids);
+    size_t id_index      = 0;
+    char SQL_STMT[LKT_MAX_SQLITE_STATEMENT]; /* The formated query to add things to the queue */
+    char IDS_LIST[LKT_LINE_MAX]; /* The thing that will hold the formated comma-separated list of ids */
+
+    SQLITE_BEGIN_TRANSATION(db, error);
+
+    while (id_index < ids_len) {
+        const size_t remaining    = MAX(ids_len - id_index, ADD_STEP);
+        size_t index_in_id_string = 0;
+
+        /* We should not enter in here, but it's fine if we do... */
+        if (remaining == 0) {
+            LOG_WARN("DB", "Don't add any more IDs because none are remaining");
+            break;
+        }
+
+        for (/* Nothing */; id_index < (id_index + remaining); ++id_index) {
+            void *const addr      = &(IDS_LIST[index_in_id_string]);
+            const size_t max_size = LKT_LINE_MAX - 1 - index_in_id_string;
+            const int added       = safe_snprintf(addr, max_size, "%zu,", ids[id_index]);
+            if (added <= 0) {
+                /* Ouups... */
+                LOG_FATAL("Failed to concatenate something to the list string, "
+                          "partial state is: %s",
+                          IDS_LIST);
+            }
+            index_in_id_string += (size_t)added;
+        }
+
+        /* Delete the last comma */
+        IDS_LIST[index_in_id_string - 1] = '\0';
+        safe_snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT, SQL_STMT_TEMPLATE, priority, IDS_LIST);
+        SQLITE_EXEC(db, SQL_STMT, error);
+    }
+
+    reorder(db, priority, error);
+    SQLITE_END_TRANSATION(db, error);
+    return true;
+
+error:
+    SQLITE_DO_ROLLBACK(db);
+    return false;
+}