diff --git a/cache.go b/cache.go
index ff4dc72..1f5b347 100644
--- a/cache.go
+++ b/cache.go
@@ -1,6 +1,9 @@
 package dataloader
 
-import "context"
+import (
+	"context"
+	"sync"
+)
 
 // The Cache interface. If a custom cache is provided, it must implement this interface.
 type Cache interface {
@@ -10,6 +13,62 @@ type Cache interface {
 	Clear()
 }
 
+// InMemoryCache is an in memory implementation of Cache interface.
+// This implementation is well suited for a "per-request" dataloader
+// (i.e. one that only lives for the life of an HTTP request)
+// but it is not well suited for long lived cached items.
+type InMemoryCache struct {
+	mu    sync.RWMutex
+	items map[interface{}]Thunk
+}
+
+// NewCache constructs a new InMemoryCache.
+func NewCache() *InMemoryCache {
+	items := make(map[interface{}]Thunk)
+	return &InMemoryCache{
+		items: items,
+	}
+}
+
+// Set the `value` at `key` in the cache.
+func (c *InMemoryCache) Set(_ context.Context, key interface{}, value Thunk) {
+	c.mu.Lock()
+	c.items[key] = value
+	c.mu.Unlock()
+}
+
+// Get the value at `key` if it exists.
+// Returns value (or nil) and whether the value was found.
+func (c *InMemoryCache) Get(_ context.Context, key interface{}) (Thunk, bool) {
+	c.mu.RLock()
+	item, found := c.items[key]
+	c.mu.RUnlock()
+
+	return item, found
+}
+
+// Delete the value at `key` from the cache.
+func (c *InMemoryCache) Delete(ctx context.Context, key interface{}) bool {
+	_, found := c.Get(ctx, key)
+
+	if found {
+		c.mu.Lock()
+		delete(c.items, key)
+		c.mu.Unlock()
+	}
+
+	return found
+}
+
+// Clear the entire cache.
+func (c *InMemoryCache) Clear() {
+	c.mu.Lock()
+	for k := range c.items {
+		delete(c.items, k)
+	}
+	c.mu.Unlock()
+}
+
 // NoCache implements Cache interface where all methods are noops.
 // This is useful for when you don't want to cache items but still
 // want to use a data loader
@@ -19,10 +78,10 @@ type NoCache struct{}
 func (c *NoCache) Get(context.Context, interface{}) (Thunk, bool) { return nil, false }
 
 // Set is a NOOP
-func (c *NoCache) Set(context.Context, interface{}, Thunk) { return }
+func (c *NoCache) Set(context.Context, interface{}, Thunk) {}
 
 // Delete is a NOOP
 func (c *NoCache) Delete(context.Context, interface{}) bool { return false }
 
 // Clear is a NOOP
-func (c *NoCache) Clear() { return }
+func (c *NoCache) Clear() {}
diff --git a/dataloader.go b/dataloader.go
index a8031d9..0732425 100644
--- a/dataloader.go
+++ b/dataloader.go
@@ -280,13 +280,16 @@ func (l *Loader) LoadMany(originalContext context.Context, keys []interface{}) T
 
 	wg.Add(length)
 	for i := range keys {
-		go func(ctx context.Context, i int) {
+		// Request the key serially to ensure the result order is maintained in key order.
+		thunk := l.Load(ctx, keys[i])
+
+		go func(ctx context.Context, i int, thunk Thunk) {
 			defer wg.Done()
-			thunk := l.Load(ctx, keys[i])
+
 			result, err := thunk()
 			data[i] = result
 			errors[i] = err
-		}(ctx, i)
+		}(ctx, i, thunk)
 	}
 
 	go func() {
diff --git a/inMemoryCache.go b/inMemoryCache.go
deleted file mode 100644
index 62b4248..0000000
--- a/inMemoryCache.go
+++ /dev/null
@@ -1,65 +0,0 @@
-// +build !go1.9
-
-package dataloader
-
-import (
-	"context"
-	"sync"
-)
-
-// InMemoryCache is an in memory implementation of Cache interface.
-// this simple implementation is well suited for
-// a "per-request" dataloader (i.e. one that only lives
-// for the life of an http request) but it not well suited
-// for long lived cached items.
-type InMemoryCache struct {
-	items map[interface{}]Thunk
-	mu    sync.RWMutex
-}
-
-// NewCache constructs a new InMemoryCache
-func NewCache() *InMemoryCache {
-	items := make(map[interface{}]Thunk)
-	return &InMemoryCache{
-		items: items,
-	}
-}
-
-// Set sets the `value` at `key` in the cache
-func (c *InMemoryCache) Set(_ context.Context, key interface{}, value Thunk) {
-	c.mu.Lock()
-	c.items[key] = value
-	c.mu.Unlock()
-}
-
-// Get gets the value at `key` if it exsits, returns value (or nil) and bool
-// indicating of value was found
-func (c *InMemoryCache) Get(_ context.Context, key interface{}) (Thunk, bool) {
-	c.mu.RLock()
-	defer c.mu.RUnlock()
-
-	item, found := c.items[key]
-	if !found {
-		return nil, false
-	}
-
-	return item, true
-}
-
-// Delete deletes item at `key` from cache
-func (c *InMemoryCache) Delete(ctx context.Context, key interface{}) bool {
-	if _, found := c.Get(ctx, key); found {
-		c.mu.Lock()
-		defer c.mu.Unlock()
-		delete(c.items, key)
-		return true
-	}
-	return false
-}
-
-// Clear clears the entire cache
-func (c *InMemoryCache) Clear() {
-	c.mu.Lock()
-	c.items = map[interface{}]Thunk{}
-	c.mu.Unlock()
-}
diff --git a/inMemoryCache_go19.go b/inMemoryCache_go19.go
deleted file mode 100644
index af5916a..0000000
--- a/inMemoryCache_go19.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// +build go1.9
-
-package dataloader
-
-import (
-	"context"
-	"sync"
-)
-
-// InMemoryCache is an in memory implementation of Cache interface.
-// this simple implementation is well suited for
-// a "per-request" dataloader (i.e. one that only lives
-// for the life of an http request) but it not well suited
-// for long lived cached items.
-type InMemoryCache struct {
-	items *sync.Map
-}
-
-// NewCache constructs a new InMemoryCache
-func NewCache() *InMemoryCache {
-	return &InMemoryCache{
-		items: &sync.Map{},
-	}
-}
-
-// Set sets the `value` at `key` in the cache
-func (c *InMemoryCache) Set(_ context.Context, key interface{}, value Thunk) {
-	c.items.Store(key, value)
-}
-
-// Get gets the value at `key` if it exsits, returns value (or nil) and bool
-// indicating of value was found
-func (c *InMemoryCache) Get(_ context.Context, key interface{}) (Thunk, bool) {
-	item, found := c.items.Load(key)
-	if !found {
-		return nil, false
-	}
-
-	return item.(Thunk), true
-}
-
-// Delete deletes item at `key` from cache
-func (c *InMemoryCache) Delete(_ context.Context, key interface{}) bool {
-	if _, found := c.items.Load(key); found {
-		c.items.Delete(key)
-		return true
-	}
-	return false
-}
-
-// Clear clears the entire cache
-func (c *InMemoryCache) Clear() {
-	c.items.Range(func(key, _ interface{}) bool {
-		c.items.Delete(key)
-		return true
-	})
-}