WIP
diff --git a/methodindex.go b/methodindex.go
new file mode 100644
index 0000000..a69d9db
--- /dev/null
+++ b/methodindex.go
@@ -0,0 +1,125 @@
+// Copyright 2019 Julien Schmidt. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be found
+// in the LICENSE file.
+
+package httprouter
+
+import (
+	"net/http"
+)
+
+const (
+	idxGET = iota
+	idxHEAD
+	idxPOST
+	idxPUT
+	idxPATCH
+	idxDELETE
+	idxCONNECT
+	idxOPTIONS
+	idxTRACE
+	idxEnd
+)
+
+type customMethod struct {
+	method string
+	root   *node
+}
+
+type methodIndex struct {
+	roots  [idxEnd]*node
+	custom []customMethod
+}
+
+func (m *methodIndex) init(method string) (root *node) {
+	var idx int
+	switch method {
+	case http.MethodGet:
+		idx = idxGET
+	case http.MethodPatch:
+		idx = idxPATCH
+	case http.MethodPost:
+		idx = idxPOST
+	case http.MethodPut:
+		idx = idxPUT
+	case http.MethodDelete:
+		idx = idxDELETE
+	case http.MethodHead:
+		idx = idxHEAD
+	case http.MethodOptions:
+		idx = idxOPTIONS
+	case http.MethodConnect:
+		idx = idxCONNECT
+	case http.MethodTrace:
+		idx = idxTRACE
+	default: // custom methods
+		for _, c := range m.custom {
+			if c.method == method {
+				return c.root
+			}
+		}
+
+		root = new(node)
+		m.custom = append(m.custom, customMethod{method, root})
+		return root
+	}
+
+	root = m.roots[idx]
+	if root == nil {
+		root = new(node)
+		m.roots[idx] = root
+	}
+	return root
+}
+
+func (m *methodIndex) get(method string) *node {
+	switch method[0] {
+	case 'G':
+		if method == http.MethodGet {
+			return m.roots[idxGET]
+		}
+	case 'P':
+		switch len(method) {
+		case 5:
+			if method == http.MethodPatch {
+				return m.roots[idxPATCH]
+			}
+		case 4:
+			if method == http.MethodPost {
+				return m.roots[idxPOST]
+			}
+		case 3:
+			if method == http.MethodPut {
+				return m.roots[idxPUT]
+			}
+		}
+	case 'D':
+		if method == http.MethodDelete {
+			return m.roots[idxDELETE]
+		}
+	case 'H':
+		if method == http.MethodHead {
+			return m.roots[idxHEAD]
+		}
+	case 'O':
+		if method == http.MethodOptions {
+			return m.roots[idxOPTIONS]
+		}
+	case 'C':
+		if method == http.MethodConnect {
+			return m.roots[idxCONNECT]
+		}
+	case 'T':
+		if method == http.MethodTrace {
+			return m.roots[idxTRACE]
+		}
+	}
+
+	// custom methods
+	for _, c := range m.custom {
+		if c.method == method {
+			return c.root
+		}
+	}
+	return nil
+}
diff --git a/router.go b/router.go
index a4e8d4e..afd9e89 100644
--- a/router.go
+++ b/router.go
@@ -124,7 +124,7 @@
 // Router is a http.Handler which can be used to dispatch requests to different
 // handler functions via configurable routes
 type Router struct {
-	trees map[string]*node
+	trees methodIndex
 
 	paramsPool sync.Pool
 	maxParams  uint16
@@ -252,16 +252,7 @@
 		panic("path must begin with '/' in path '" + path + "'")
 	}
 
-	if r.trees == nil {
-		r.trees = make(map[string]*node)
-	}
-
-	root := r.trees[method]
-	if root == nil {
-		root = new(node)
-		r.trees[method] = root
-	}
-
+	root := r.trees.init(method)
 	root.addRoute(path, handle)
 
 	// Update maxParams
@@ -335,7 +326,7 @@
 // values. Otherwise the third return value indicates whether a redirection to
 // the same path with an extra / without the trailing slash should be performed.
 func (r *Router) Lookup(method, path string) (Handle, Params, bool) {
-	if root := r.trees[method]; root != nil {
+	if root := r.trees.get(method); root != nil {
 		handle, ps, tsr := root.getValue(path, r.getParams)
 		if handle == nil {
 			r.putParams(ps)
@@ -347,37 +338,37 @@
 }
 
 func (r *Router) allowed(path, reqMethod string) (allow string) {
-	if path == "*" { // server-wide
-		for method := range r.trees {
-			if method == http.MethodOptions {
-				continue
-			}
+	// if path == "*" { // server-wide
+	// 	for i, tree := range r.trees {
+	// 		if i == idxOPTIONS || tree == nil {
+	// 			continue
+	// 		}
 
-			// add request method to list of allowed methods
-			if len(allow) == 0 {
-				allow = method
-			} else {
-				allow += ", " + method
-			}
-		}
-	} else { // specific path
-		for method := range r.trees {
-			// Skip the requested method - we already tried this one
-			if method == reqMethod || method == http.MethodOptions {
-				continue
-			}
+	// 		// add request method to list of allowed methods
+	// 		if len(allow) == 0 {
+	// 			allow = method
+	// 		} else {
+	// 			allow += ", " + method
+	// 		}
+	// 	}
+	// 	} else { // specific path
+	// 		for method := range r.trees {
+	// 			// Skip the requested method - we already tried this one
+	// 			if method == reqMethod || method == http.MethodOptions {
+	// 				continue
+	// 			}
 
-			handle, _, _ := r.trees[method].getValue(path, nil)
-			if handle != nil {
-				// add request method to list of allowed methods
-				if len(allow) == 0 {
-					allow = method
-				} else {
-					allow += ", " + method
-				}
-			}
-		}
-	}
+	// 			handle, _, _ := r.trees[method].getValue(path)
+	// 			if handle != nil {
+	// 				// add request method to list of allowed methods
+	// 				if len(allow) == 0 {
+	// 					allow = method
+	// 				} else {
+	// 					allow += ", " + method
+	// 				}
+	// 			}
+	// 		}
+	// }
 	if len(allow) > 0 {
 		allow += ", OPTIONS"
 	}
@@ -392,7 +383,7 @@
 
 	path := req.URL.Path
 
-	if root := r.trees[req.Method]; root != nil {
+	if root := r.trees.get(req.Method); root != nil {
 		if handle, psp, tsr := root.getValue(path, r.getParams); handle != nil {
 			var ps Params
 			if psp != nil {