diff --git a/db/namespace.cpp b/db/namespace.cpp
index 210efb6..b3f5681 100644
--- a/db/namespace.cpp
+++ b/db/namespace.cpp
@@ -551,28 +551,76 @@ namespace mongo {
         return loc;
     }
 
+    /* extra space for indexes when more than 10 */
+    NamespaceDetails::Extra* NamespaceIndex::newExtra(const char *ns, int i, NamespaceDetails *d) {
+        assert( i >= 0 && i <= 1 );
+        Namespace n(ns);
+        Namespace extra(n.extraName(i).c_str()); // throws userexception if ns name too long
+        
+        massert( 10350 ,  "allocExtra: base ns missing?", d );
+        massert( 10351 ,  "allocExtra: extra already exists", ht->get(extra) == 0 );
+
+        NamespaceDetails::Extra temp;
+        temp.init();
+        uassert( 10082 ,  "allocExtra: too many namespaces/collections", ht->put(extra, (NamespaceDetails&) temp));
+        NamespaceDetails::Extra *e = (NamespaceDetails::Extra *) ht->get(extra);
+        return e;
+    }
+    NamespaceDetails::Extra* NamespaceDetails::allocExtra(const char *ns, int nindexessofar) {
+        NamespaceIndex *ni = nsindex(ns);
+        int i = (nindexessofar - NIndexesBase) / NIndexesExtra;
+        Extra *e = ni->newExtra(ns, i, this);
+        long ofs = e->ofsFrom(this);
+        if( i == 0 ) {
+            assert( extraOffset == 0 );
+            extraOffset = ofs;
+            assert( extra() == e );
+        }
+        else { 
+            Extra *hd = extra();
+            assert( hd->next(this) == 0 );
+            hd->setNext(ofs);
+        }
+        return e;
+    }
+
     /* you MUST call when adding an index.  see pdfile.cpp */
     IndexDetails& NamespaceDetails::addIndex(const char *thisns, bool resetTransient) {
         assert( nsdetails(thisns) == this );
 
-        if( nIndexes == NIndexesBase && extraOffset == 0 ) { 
-            nsindex(thisns)->allocExtra(thisns);
+        IndexDetails *id;
+        try {
+            id = &idx(nIndexes);
+        }
+        catch(DBException&) { 
+            allocExtra(thisns, nIndexes);
+            id = &idx(nIndexes);
         }
 
-        IndexDetails& id = idx(nIndexes);
         nIndexes++;
         if ( resetTransient )
             NamespaceDetailsTransient::get_w(thisns).addedIndex();
-        return id;
+        return *id;
     }
 
     // must be called when renaming a NS to fix up extra
     void NamespaceDetails::copyingFrom(const char *thisns, NamespaceDetails *src) { 
-        if( extraOffset ) {
-            extraOffset = 0; // so allocExtra() doesn't assert.
-            Extra *e = nsindex(thisns)->allocExtra(thisns);
-            memcpy(e, src->extra(), sizeof(Extra));
-        } 
+        extraOffset = 0; // we are a copy -- the old value is wrong.  fixing it up below.
+        Extra *se = src->extra();
+        int n = NIndexesBase;
+        if( se ) {
+            Extra *e = allocExtra(thisns, n);
+            while( 1 ) {
+                n += NIndexesExtra;
+                e->copy(this, *se);
+                se = se->next(src);
+                if( se == 0 ) break;
+                Extra *nxt = allocExtra(thisns, n);
+                e->setNext( nxt->ofsFrom(this) );
+                e = nxt;
+            } 
+            assert( extraOffset );
+        }
     }
 
     /* returns index of the first index in which the field is present. -1 if not present.
diff --git a/db/namespace.h b/db/namespace.h
index 1b1a954..8735b00 100644
--- a/db/namespace.h
+++ b/db/namespace.h
@@ -29,8 +29,6 @@ namespace mongo {
 
     class Cursor;
 
-#pragma pack(1)
-
 	/* in the mongo source code, "client" means "database". */
 
     const int MaxDatabaseLen = 256; // max str len for the db name, including null char
@@ -84,6 +82,7 @@ namespace mongo {
         }
     };
 
+#pragma pack(1)
 	/* This helper class is used to make the HashMap below in NamespaceDetails */
     class Namespace {
     public:
@@ -99,14 +98,16 @@ namespace mongo {
         }
 
         /* for more than 10 indexes -- see NamespaceDetails::Extra */
-        string extraName() { 
-            string s = string(buf) + "$extra";
-            massert( 10348 , "ns name too long", s.size() < MaxNsLen);
+        string extraName(int i) { 
+            char ex[] = "$extra";
+            ex[5] += i;
+            string s = string(buf) + ex;
+            massert( 10348 , "$extra: ns name too long", s.size() < MaxNsLen);
             return s;
         }
         bool isExtra() const { 
-            const char *p = strstr(buf, "$extra");
-            return p && p[6] == 0; //==0 important in case an index uses name "$extra_1" for example
+            const char *p = strstr(buf, "$extr");
+            return p && p[5] && p[6] == 0; //==0 important in case an index uses name "$extra_1" for example
         }
 
         void kill() {
@@ -147,8 +148,9 @@ namespace mongo {
 
         char buf[MaxNsLen];
     };
+#pragma pack()
 
-}
+} // namespace mongo
 
 #include "index.h"
 
@@ -169,6 +171,7 @@ namespace mongo {
 
     extern int bucketSizes[];
 
+#pragma pack(1)
     /* this is the "header" for a collection that has all its details.  in the .ns file.
     */
     class NamespaceDetails {
@@ -176,23 +179,55 @@ namespace mongo {
         enum { NIndexesExtra = 30,
                NIndexesBase  = 10
         };
-        struct Extra { 
+        struct ExtraOld {
             // note we could use this field for more chaining later, so don't waste it:
-            unsigned long long reserved1; 
+            unsigned long long reserved1;
             IndexDetails details[NIndexesExtra];
             unsigned reserved2;
             unsigned reserved3;
         };
+        class Extra { 
+            long long _next;
+		public:
+            IndexDetails details[NIndexesExtra];
+		private:
+            unsigned reserved2;
+            unsigned reserved3;
+			Extra(const Extra&) { assert(false); }
+			Extra& operator=(const Extra& r) { assert(false); return *this; }
+        public:
+            Extra() { }
+            long ofsFrom(NamespaceDetails *d) { 
+                return ((char *) this) - ((char *) d);
+            }
+            void init() { memset(this, 0, sizeof(Extra)); }
+            Extra* next(NamespaceDetails *d) { 
+                if( _next == 0 ) return 0;
+                return (Extra*) (((char *) d) + _next);
+            }
+            void setNext(long ofs) { _next = ofs;  }
+            void copy(NamespaceDetails *d, const Extra& e) { 
+                memcpy(this, &e, sizeof(Extra));
+                _next = 0;
+            }
+        }; // Extra
+
         Extra* extra() { 
-            assert( extraOffset );
+            if( extraOffset == 0 ) return 0;
             return (Extra *) (((char *) this) + extraOffset);
         }
     public:
+        /* add extra space for indexes when more than 10 */
+        Extra* allocExtra(const char *ns, int nindexessofar);
+
         void copyingFrom(const char *thisns, NamespaceDetails *src); // must be called when renaming a NS to fix up extra
 
-        enum { NIndexesMax = 40 };
+        enum { NIndexesMax = 64 };
 
-        BOOST_STATIC_ASSERT( NIndexesMax == NIndexesBase + NIndexesExtra );
+        BOOST_STATIC_ASSERT( NIndexesMax <= NIndexesBase + NIndexesExtra*2 );
+        BOOST_STATIC_ASSERT( NIndexesMax <= 64 ); // multiKey bits
+		BOOST_STATIC_ASSERT( sizeof(NamespaceDetails::ExtraOld) == 496 );
+		BOOST_STATIC_ASSERT( sizeof(NamespaceDetails::Extra) == 496 );
 
         /* called when loaded from disk */
         void onLoad(const Namespace& k);
@@ -280,7 +315,15 @@ namespace mongo {
         IndexDetails& idx(int idxNo) {
             if( idxNo < NIndexesBase ) 
                 return _indexes[idxNo];
-            return extra()->details[idxNo-NIndexesBase];
+            Extra *e = extra();
+            massert(13282, "missing Extra", e);
+            int i = idxNo - NIndexesBase;
+            if( i >= NIndexesExtra ) {
+                e = e->next(this);
+                massert(13283, "missing Extra", e);
+                i -= NIndexesExtra;
+            }
+            return e->details[i];
         }
         IndexDetails& backgroundIdx() { 
             DEV assert(backgroundIndexBuildInProgress);
@@ -292,23 +335,15 @@ namespace mongo {
             int i;
             int n;
             NamespaceDetails *d;
-            Extra *e;
             IndexIterator(NamespaceDetails *_d) { 
                 d = _d;
                 i = 0;
                 n = d->nIndexes;
-                if( n > NIndexesBase )
-                    e = d->extra();
             }
         public:
             int pos() { return i; } // note this is the next one to come
             bool more() { return i < n; }
-            IndexDetails& next() { 
-                int k = i;
-                i++;
-                return k < NIndexesBase ? d->_indexes[k] : 
-                    e->details[k-10];
-            }
+            IndexDetails& next() { return d->idx(i++); }
         };
 
         IndexIterator ii() { 
@@ -465,6 +500,8 @@ namespace mongo {
        todo: cleanup code, need abstractions and separation
     */
     class NamespaceDetailsTransient : boost::noncopyable {
+		BOOST_STATIC_ASSERT( sizeof(NamespaceDetails) == 496 );
+
         /* general ------------------------------------------------------------- */
     private:
         string _ns;
@@ -578,7 +615,7 @@ namespace mongo {
     */
     class NamespaceIndex {
         friend class NamespaceCursor;
-        BOOST_STATIC_ASSERT( sizeof(NamespaceDetails::Extra) <= sizeof(NamespaceDetails) );
+
     public:
         NamespaceIndex(const string &dir, const string &database) :
           ht( 0 ),
@@ -608,23 +645,6 @@ namespace mongo {
             return ((char *) d) -  (char *) ht->nodes;
         }
 
-        /* extra space for indexes when more than 10 */
-        NamespaceDetails::Extra* allocExtra(const char *ns) { 
-            Namespace n(ns);
-            Namespace extra(n.extraName().c_str()); // throws userexception if ns name too long
-            NamespaceDetails *d = details(ns);
-            massert( 10350 ,  "allocExtra: base ns missing?", d );
-            assert( d->extraOffset == 0 );
-            massert( 10351 ,  "allocExtra: extra already exists", ht->get(extra) == 0 );
-            NamespaceDetails::Extra temp;
-            memset(&temp, 0, sizeof(temp));
-            uassert( 10082 ,  "allocExtra: too many namespaces/collections", ht->put(extra, (NamespaceDetails&) temp));
-            NamespaceDetails::Extra *e = (NamespaceDetails::Extra *) ht->get(extra);
-            d->extraOffset = ((char *) e) - ((char *) d);
-            assert( d->extra() == e );
-            return e;
-        }
-
         NamespaceDetails* details(const char *ns) {
             if ( !ht )
                 return 0;
@@ -641,11 +661,13 @@ namespace mongo {
             Namespace n(ns);
             ht->kill(n);
 
-            try {
-                Namespace extra(n.extraName().c_str());
-                ht->kill(extra);
+            for( int i = 0; i<=1; i++ ) {
+                try {
+                    Namespace extra(n.extraName(i).c_str());
+                    ht->kill(extra);
+                }
+                catch(DBException&) { }
             }
-            catch(DBException&) { }
         }
 
         bool find(const char *ns, DiskLoc& loc) {
@@ -661,6 +683,8 @@ namespace mongo {
             return ht != 0;
         }
 
+        NamespaceDetails::Extra* newExtra(const char *ns, int n, NamespaceDetails *d);
+
     private:
         boost::filesystem::path path() const;
         void maybeMkdir() const;
diff --git a/jstests/index_many.js b/jstests/index_many.js
index 9960afa..3fca5f5 100644
--- a/jstests/index_many.js
+++ b/jstests/index_many.js
@@ -1,34 +1,29 @@
-t = db.many;
-
-t.drop();
-db.many2.drop();
-
-t.save({x:9});
-t.save({x:19});
-
-x = 2;
-while( x < 60 ) { 
-    patt={};
-    patt[x] = 1;
-    if( x == 20 )
-	patt = { x : 1 };
-    t.ensureIndex(patt);
-    x++;
-}
 
-// print( tojson(db.getLastErrorObj()) );
-assert( db.getLastError(), "should have an error 'too many indexes'" );
+t = db.index_many2;
+t.drop()
+
+t.save( { x : 1 } )
+
+assert.eq( 1 , t.getIndexKeys().length , "A1" )
 
-// 40 is the limit currently
+function make( n ){
+    var x = {}
+    x["x"+n] = 1;
+    return x;
+}
+
+for ( i=1; i<1000; i++ ){
+    t.ensureIndex( make(i) );
+}
 
-// print( t.getIndexes().length == 40, "40" );
+assert.eq( 64 , t.getIndexKeys().length , "A2" )
 
-assert( t.getIndexes().length == 40, "40" );
 
-assert( t.find({x:9}).length() == 1, "b" ) ;
+num = t.getIndexKeys().length
 
-t.renameCollection( "many2" );
+t.dropIndex( make(num-1) )
+assert.eq( num - 1 , t.getIndexKeys().length , "B0" )
 
-assert( t.find({x:9}).length() == 0, "c" ) ;
+t.ensureIndex( { z : 1 } )
+assert.eq( num  , t.getIndexKeys().length , "B1" )
 
-assert( db.many2.find({x:9}).length() == 1, "d" ) ;
