off_t            size;
        MDB_page        *dp;
        MDB_env *env;
-       pgno_t  next, freecnt;
+       pgno_t  next, freecnt, maxfree_1pg;
        txnid_t oldpg_txnid, id;
        MDB_cursor mc;
 
        /* Save the freelist as of this transaction to the freeDB. This
         * can change the freelist, so keep trying until it stabilizes.
         *
-        * env->me_pglast and the length of txn->mt_free_pgs cannot decrease.
+        * env->me_pglast and the length of txn->mt_free_pgs cannot decrease,
+        * except the code below can decrease env->me_pglast to split pghead.
         * Page numbers cannot disappear from txn->mt_free_pgs.  New pages
         * can only appear in env->me_pghead when env->me_pglast increases.
         * Until then, the me_pghead pointer won't move but can become NULL.
        mdb_cursor_init(&mc, txn, FREE_DBI, NULL);
        oldpg_txnid = id = 0;
        freecnt = 0;
+       /* Preferred max #items per freelist entry, to avoid overflow pages.
+        * Leave room for headers, key (txnid), pagecount (pageno_t), and
+        * FIXME: a bit more in case there is some delimiter I don't know about.
+        */
+       maxfree_1pg = (env->me_psize - (PAGEHDRSZ + NODESIZE + 3*sizeof(MDB_ID)))
+               / sizeof(pgno_t);
 
        /* should only be one record now */
        if (env->me_pghead || env->me_pglast) {
 
        /* Put back page numbers we took from freeDB but did not use */
        if (env->me_pghead) {
+         for (;;) {
                MDB_val key, data;
                pgno_t orig, *mop;
 
                i = 2;
                do {
                        orig = mop[0];
-                       data.mv_size = MDB_IDL_SIZEOF(mop);
+                       if (orig > maxfree_1pg && id > 4)
+                               orig = maxfree_1pg; /* Do not use an overflow page */
+                       data.mv_size = (orig + 1) * sizeof(pgno_t);
                        rc = mdb_cursor_put(&mc, &key, &data, MDB_RESERVE);
                        if (rc)
                                goto fail;
                        /* mop could have been used again here */
                        if (id != env->me_pglast || env->me_pghead == NULL)
                                goto again;             /* was completely used up */
-                       assert(mop == env->me_pghead && mop[0] <= orig);
-               } while (mop[0] != orig && --i);
+                       assert(mop == env->me_pghead);
+               } while (mop[0] < orig && --i);
                memcpy(data.mv_data, mop, data.mv_size);
+               if (mop[0] <= orig)
+                       break;
+               *(pgno_t *)data.mv_data = orig;
+               mop[0] -= orig;
+               memmove(&mop[1], &mop[1 + orig],
+                       mop[0] * sizeof(pgno_t));
+               /* Save more oldpages at the previous txnid. */
+               assert(env->me_pglast == id && id == oldpg_txnid);
+               env->me_pglast = --oldpg_txnid;
+         }
        }
 
        /* Check for growth of freelist again */