diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp
index afcb7697997..ee3855c127f 100644
--- a/libgnucash/engine/Account.cpp
+++ b/libgnucash/engine/Account.cpp
@@ -311,7 +311,6 @@ gnc_account_init(Account* acc)
     priv->mark = 0;
 
     priv->policy = xaccGetFIFOPolicy();
-    priv->lots = nullptr;
 
     priv->commodity = nullptr;
     priv->commodity_scu = 0;
@@ -327,6 +326,7 @@ gnc_account_init(Account* acc)
     priv->starting_reconciled_balance = gnc_numeric_zero();
     priv->balance_dirty = FALSE;
 
+    new (&priv->lots) LotVec ();
     new (&priv->children) AccountVec ();
     new (&priv->splits) SplitsVec ();
     priv->splits_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
@@ -1372,7 +1372,6 @@ static void
 xaccFreeAccount (Account *acc)
 {
     AccountPrivate *priv;
-    GList *lp;
 
     g_return_if_fail(GNC_IS_ACCOUNT(acc));
 
@@ -1395,18 +1394,13 @@ xaccFreeAccount (Account *acc)
     }
 
     /* remove lots -- although these should be gone by now. */
-    if (priv->lots)
+    if (!priv->lots.empty())
     {
         PERR (" instead of calling xaccFreeAccount(), please call\n"
               " xaccAccountBeginEdit(); xaccAccountDestroy();\n");
 
-        for (lp = priv->lots; lp; lp = lp->next)
-        {
-            GNCLot *lot = static_cast<GNCLot*>(lp->data);
-            gnc_lot_destroy (lot);
-        }
-        g_list_free (priv->lots);
-        priv->lots = nullptr;
+        std::for_each (priv->lots.rbegin(), priv->lots.rend(), gnc_lot_destroy);
+        priv->lots.~LotVec();
     }
 
     /* Next, clean up the splits */
@@ -1566,14 +1560,10 @@ xaccAccountCommitEdit (Account *acc)
             qof_collection_foreach(col, destroy_pending_splits_for_account, acc);
 
             /* the lots should be empty by now */
-            for (auto lp = priv->lots; lp; lp = lp->next)
-            {
-                GNCLot *lot = static_cast<GNCLot*>(lp->data);
-                gnc_lot_destroy (lot);
-            }
+            std::for_each (priv->lots.rbegin(), priv->lots.rend(), gnc_lot_destroy);
         }
-        g_list_free(priv->lots);
-        priv->lots = nullptr;
+        priv->lots.clear();     // this is crucial otherwise test-engine fails
+        priv->lots.~LotVec();
 
         qof_instance_set_dirty(&acc->inst);
         qof_instance_decrease_editlevel(acc);
@@ -2109,10 +2099,10 @@ xaccAccountRemoveLot (Account *acc, GNCLot *lot)
     g_return_if_fail(GNC_IS_LOT(lot));
 
     priv = GET_PRIVATE(acc);
-    g_return_if_fail(priv->lots);
+    g_return_if_fail(!priv->lots.empty());
 
     ENTER ("(acc=%p, lot=%p)", acc, lot);
-    priv->lots = g_list_remove(priv->lots, lot);
+    priv->lots.erase (std::remove (priv->lots.begin(), priv->lots.end(), lot), priv->lots.end());
     qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_REMOVE, nullptr);
     qof_event_gen (&acc->inst, QOF_EVENT_MODIFY, nullptr);
     LEAVE ("(acc=%p, lot=%p)", acc, lot);
@@ -2121,16 +2111,12 @@ xaccAccountRemoveLot (Account *acc, GNCLot *lot)
 void
 xaccAccountInsertLot (Account *acc, GNCLot *lot)
 {
-    AccountPrivate *priv, *opriv;
-    Account * old_acc = nullptr;
-    Account* lot_account;
-
     /* errors */
     g_return_if_fail(GNC_IS_ACCOUNT(acc));
     g_return_if_fail(GNC_IS_LOT(lot));
 
     /* optimizations */
-    lot_account = gnc_lot_get_account(lot);
+    auto lot_account = gnc_lot_get_account(lot);
     if (lot_account == acc)
         return;
 
@@ -2139,13 +2125,12 @@ xaccAccountInsertLot (Account *acc, GNCLot *lot)
     /* pull it out of the old account */
     if (lot_account)
     {
-        old_acc = lot_account;
-        opriv = GET_PRIVATE(old_acc);
-        opriv->lots = g_list_remove(opriv->lots, lot);
+        auto& lot_acc_lots = GET_PRIVATE(lot_account)->lots;
+        lot_acc_lots.erase (std::remove (lot_acc_lots.begin(), lot_acc_lots.end(), lot),
+                            lot_acc_lots.end());
     }
 
-    priv = GET_PRIVATE(acc);
-    priv->lots = g_list_prepend(priv->lots, lot);
+    GET_PRIVATE(acc)->lots.push_back (lot);
     gnc_lot_set_account(lot, acc);
 
     /* Don't move the splits to the new account.  The caller will do this
@@ -2221,7 +2206,7 @@ xaccAccountMoveAllSplits (Account *accfrom, Account *accto)
 
     /* Finally empty accfrom. */
     g_assert(from_priv->splits.empty());
-    g_assert(from_priv->lots == nullptr);
+    g_assert(from_priv->lots.empty());
     xaccAccountCommitEdit(accfrom);
     xaccAccountCommitEdit(accto);
 
@@ -3918,7 +3903,9 @@ LotList *
 xaccAccountGetLotList (const Account *acc)
 {
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), nullptr);
-    return g_list_copy(GET_PRIVATE(acc)->lots);
+    auto priv = GET_PRIVATE (acc);
+    return std::accumulate (priv->lots.rbegin(), priv->lots.rend(),
+                            static_cast<GList*>(nullptr), g_list_prepend);
 }
 
 LotList *
@@ -3928,16 +3915,13 @@ xaccAccountFindOpenLots (const Account *acc,
                          gpointer user_data, GCompareFunc sort_func)
 {
     AccountPrivate *priv;
-    GList *lot_list;
     GList *retval = nullptr;
 
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), nullptr);
 
     priv = GET_PRIVATE(acc);
-    for (lot_list = priv->lots; lot_list; lot_list = lot_list->next)
+    for (auto lot : priv->lots)
     {
-        GNCLot *lot = static_cast<GNCLot*>(lot_list->data);
-
         /* If this lot is closed, then ignore it */
         if (gnc_lot_is_closed (lot))
             continue;
@@ -3962,8 +3946,8 @@ xaccAccountForEachLot(const Account *acc,
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), nullptr);
     g_return_val_if_fail(proc, nullptr);
 
-    for (auto node = GET_PRIVATE(acc)->lots; node; node = node->next)
-        if (auto result = proc(GNC_LOT(node->data), data))
+    for (auto lot : GET_PRIVATE(acc)->lots)
+        if (auto result = proc(lot, data))
             return result;
 
     return nullptr;
diff --git a/libgnucash/engine/Account.hpp b/libgnucash/engine/Account.hpp
index 89649acfc48..6d13b1c5d08 100644
--- a/libgnucash/engine/Account.hpp
+++ b/libgnucash/engine/Account.hpp
@@ -39,6 +39,7 @@
 
 using SplitsVec = std::vector<Split*>;
 using AccountVec = std::vector<Account*>;
+using LotVec = std::vector<GNCLot*>;
 
 const SplitsVec& xaccAccountGetSplits (const Account*);
 
diff --git a/libgnucash/engine/AccountP.hpp b/libgnucash/engine/AccountP.hpp
index ea617fe0118..9945fe5289a 100644
--- a/libgnucash/engine/AccountP.hpp
+++ b/libgnucash/engine/AccountP.hpp
@@ -119,7 +119,7 @@ typedef struct AccountPrivate
     GHashTable* splits_hash;
     gboolean sort_dirty;        /* sort order of splits is bad */
 
-    LotList   *lots;		/* list of lot pointers */
+    std::vector<GNCLot*> lots;		/* list of lot pointers */
     GNCPolicy *policy;		/* Cached pointer to policy method */
 
     char *notes;
diff --git a/libgnucash/engine/test/utest-Account.cpp b/libgnucash/engine/test/utest-Account.cpp
index 7f8585c17de..69ed1dd3349 100644
--- a/libgnucash/engine/test/utest-Account.cpp
+++ b/libgnucash/engine/test/utest-Account.cpp
@@ -881,7 +881,7 @@ test_xaccFreeAccount (Fixture *fixture, gconstpointer pData)
     xaccAccountSetCommodity (parent, commodity);
     /* Check that we've got children, lots, and splits to remove */
     g_assert_true (!p_priv->children.empty());
-    g_assert_true (p_priv->lots != NULL);
+    g_assert_true (!p_priv->lots.empty());
     g_assert_true (p_priv->splits.size());
     g_assert_true (p_priv->parent != NULL);
     g_assert_true (p_priv->commodity != NULL);
@@ -982,7 +982,7 @@ test_xaccAccountCommitEdit (Fixture *fixture, gconstpointer pData)
     xaccAccountSetCommodity (parent, commodity);
     /* Check that we've got children, lots, and splits to remove */
     g_assert_true (!p_priv->children.empty());
-    g_assert_true (p_priv->lots != NULL);
+    g_assert_true (!p_priv->lots.empty());
     g_assert_true (p_priv->splits.size());
     g_assert_true (p_priv->parent != NULL);
     g_assert_true (p_priv->commodity != NULL);
@@ -997,7 +997,7 @@ test_xaccAccountCommitEdit (Fixture *fixture, gconstpointer pData)
     test_signal_assert_hits (sig1, 1);
     test_signal_assert_hits (sig2, 0);
     g_assert_true (!p_priv->children.empty());
-    g_assert_true (p_priv->lots != NULL);
+    g_assert_true (!p_priv->lots.empty());
     g_assert_true (p_priv->splits.size());
     g_assert_true (p_priv->parent != NULL);
     g_assert_true (p_priv->commodity != NULL);
@@ -1530,24 +1530,24 @@ test_xaccAccountInsertRemoveLot (Fixture *fixture, gconstpointer pData)
     AccountPrivate *a_priv = fixture->func->get_private (fixture->acct);
     AccountPrivate *p_priv = fixture->func->get_private (parent);
 
-    g_assert_cmpuint (g_list_length (a_priv->lots), == , 0);
-    g_assert_cmpuint (g_list_length (p_priv->lots), == , 0);
+    g_assert_cmpuint (a_priv->lots.size(), == , 0);
+    g_assert_cmpuint (p_priv->lots.size(), == , 0);
     xaccAccountInsertLot (fixture->acct, lot);
     g_assert_true (gnc_lot_get_account (lot) == fixture->acct);
-    g_assert_cmpuint (g_list_length (a_priv->lots), == , 1);
+    g_assert_cmpuint (a_priv->lots.size(), == , 1);
     test_signal_assert_hits (sig1, 1);
     test_signal_assert_hits (sig2, 1);
     /* Make sure that inserting again doesn't do anything */
     xaccAccountInsertLot (fixture->acct, lot);
     g_assert_true (gnc_lot_get_account (lot) == fixture->acct);
-    g_assert_cmpuint (g_list_length (a_priv->lots), == , 1);
+    g_assert_cmpuint (a_priv->lots.size(), == , 1);
     test_signal_assert_hits (sig1, 1);
     test_signal_assert_hits (sig2, 1);
     /* Check that inserting the lot into a different account changes the lot */
     xaccAccountInsertLot (parent, lot);
     g_assert_true (gnc_lot_get_account (lot) == parent);
-    g_assert_cmpuint (g_list_length (a_priv->lots), == , 0);
-    g_assert_cmpuint (g_list_length (p_priv->lots), == , 1);
+    g_assert_cmpuint (a_priv->lots.size(), == , 0);
+    g_assert_cmpuint (p_priv->lots.size(), == , 1);
     test_signal_assert_hits (sig1, 2);
     test_signal_assert_hits (sig4, 1);
     test_signal_assert_hits (sig2, 1);
@@ -1557,8 +1557,8 @@ test_xaccAccountInsertRemoveLot (Fixture *fixture, gconstpointer pData)
      * error in the routine: When removing a lot from an account, the
      * account reference in the lot object should be NULLed. */
     g_assert_true (gnc_lot_get_account (lot) != NULL);
-    g_assert_cmpuint (g_list_length (a_priv->lots), == , 0);
-    g_assert_cmpuint (g_list_length (p_priv->lots), == , 0);
+    g_assert_cmpuint (a_priv->lots.size(), == , 0);
+    g_assert_cmpuint (p_priv->lots.size(), == , 0);
     test_signal_assert_hits (sig3, 1);
     test_signal_assert_hits (sig4, 2);
     test_signal_assert_hits (sig2, 1);
@@ -1567,11 +1567,11 @@ test_xaccAccountInsertRemoveLot (Fixture *fixture, gconstpointer pData)
      * is removed, we have to do that for the next test to work: */
     gnc_lot_set_account (lot, NULL);
     xaccAccountInsertLot (parent, lot);
-    g_assert_cmpuint (g_list_length (p_priv->lots), == , 1);
+    g_assert_cmpuint (p_priv->lots.size(), == , 1);
     g_assert_true (gnc_lot_get_account (lot) == parent);
     gnc_lot_destroy (lot);
     /* Destroying the lot should remove it from the account. */
-    g_assert_cmpuint (g_list_length (p_priv->lots), == , 0);
+    g_assert_cmpuint (p_priv->lots.size(), == , 0);
     test_signal_assert_hits (sig1, 3);
     test_signal_assert_hits (sig3, 2);
     test_signal_assert_hits (sig4, 4);