diff --git a/bind.go b/bind.go
index ed7ca3249..2959fff33 100644
--- a/bind.go
+++ b/bind.go
@@ -17,7 +17,7 @@ import (
 
 // Binder is the interface that wraps the Bind method.
 type Binder interface {
-	Bind(i interface{}, c Context) error
+	Bind(i any, c Context) error
 }
 
 // DefaultBinder is the default implementation of the Binder interface.
@@ -39,7 +39,7 @@ type bindMultipleUnmarshaler interface {
 }
 
 // BindPathParams binds path params to bindable object
-func (b *DefaultBinder) BindPathParams(c Context, i interface{}) error {
+func (b *DefaultBinder) BindPathParams(c Context, i any) error {
 	names := c.ParamNames()
 	values := c.ParamValues()
 	params := map[string][]string{}
@@ -53,7 +53,7 @@ func (b *DefaultBinder) BindPathParams(c Context, i interface{}) error {
 }
 
 // BindQueryParams binds query params to bindable object
-func (b *DefaultBinder) BindQueryParams(c Context, i interface{}) error {
+func (b *DefaultBinder) BindQueryParams(c Context, i any) error {
 	if err := b.bindData(i, c.QueryParams(), "query", nil); err != nil {
 		return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
 	}
@@ -65,7 +65,7 @@ func (b *DefaultBinder) BindQueryParams(c Context, i interface{}) error {
 // which parses form data from BOTH URL and BODY if content type is not MIMEMultipartForm
 // See non-MIMEMultipartForm: https://golang.org/pkg/net/http/#Request.ParseForm
 // See MIMEMultipartForm: https://golang.org/pkg/net/http/#Request.ParseMultipartForm
-func (b *DefaultBinder) BindBody(c Context, i interface{}) (err error) {
+func (b *DefaultBinder) BindBody(c Context, i any) (err error) {
 	req := c.Request()
 	if req.ContentLength == 0 {
 		return
@@ -117,7 +117,7 @@ func (b *DefaultBinder) BindBody(c Context, i interface{}) (err error) {
 }
 
 // BindHeaders binds HTTP headers to a bindable object
-func (b *DefaultBinder) BindHeaders(c Context, i interface{}) error {
+func (b *DefaultBinder) BindHeaders(c Context, i any) error {
 	if err := b.bindData(i, c.Request().Header, "header", nil); err != nil {
 		return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
 	}
@@ -127,7 +127,7 @@ func (b *DefaultBinder) BindHeaders(c Context, i interface{}) error {
 // Bind implements the `Binder#Bind` function.
 // Binding is done in following order: 1) path params; 2) query params; 3) request body. Each step COULD override previous
 // step binded values. For single source binding use their own methods BindBody, BindQueryParams, BindPathParams.
-func (b *DefaultBinder) Bind(i interface{}, c Context) (err error) {
+func (b *DefaultBinder) Bind(i any, c Context) (err error) {
 	if err := b.BindPathParams(c, i); err != nil {
 		return err
 	}
@@ -144,7 +144,7 @@ func (b *DefaultBinder) Bind(i interface{}, c Context) (err error) {
 }
 
 // bindData will bind data ONLY fields in destination struct that have EXPLICIT tag
-func (b *DefaultBinder) bindData(destination interface{}, data map[string][]string, tag string, dataFiles map[string][]*multipart.FileHeader) error {
+func (b *DefaultBinder) bindData(destination any, data map[string][]string, tag string, dataFiles map[string][]*multipart.FileHeader) error {
 	if destination == nil || (len(data) == 0 && len(dataFiles) == 0) {
 		return nil
 	}
@@ -155,7 +155,7 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
 	// Support binding to limited Map destinations:
 	// - map[string][]string,
 	// - map[string]string <-- (binds first value from data slice)
-	// - map[string]interface{}
+	// - map[string]any
 	// You are better off binding to struct but there are user who want this map feature. Source of data for these cases are:
 	// params,query,header,form as these sources produce string values, most of the time slice of strings, actually.
 	if typ.Kind() == reflect.Map && typ.Key().Kind() == reflect.String {
@@ -174,7 +174,7 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
 				val.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(v[0]))
 			} else if isElemInterface {
 				// To maintain backward compatibility, we always bind to the first string value
-				// and not the slice of strings when dealing with map[string]interface{}{}
+				// and not the slice of strings when dealing with map[string]any{}
 				val.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(v[0]))
 			} else {
 				val.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(v))
diff --git a/bind_test.go b/bind_test.go
index c79669c8c..ba430b68d 100644
--- a/bind_test.go
+++ b/bind_test.go
@@ -493,10 +493,10 @@ func TestDefaultBinder_bindDataToMap(t *testing.T) {
 	})
 
 	t.Run("ok, bind to map[string]interface", func(t *testing.T) {
-		dest := map[string]interface{}{}
+		dest := map[string]any{}
 		assert.NoError(t, new(DefaultBinder).bindData(&dest, exampleData, "param", nil))
 		assert.Equal(t,
-			map[string]interface{}{
+			map[string]any{
 				"multiple": "1",
 				"single":   "3",
 			},
@@ -505,10 +505,10 @@ func TestDefaultBinder_bindDataToMap(t *testing.T) {
 	})
 
 	t.Run("ok, bind to map[string]interface with nil map", func(t *testing.T) {
-		var dest map[string]interface{}
+		var dest map[string]any
 		assert.NoError(t, new(DefaultBinder).bindData(&dest, exampleData, "param", nil))
 		assert.Equal(t,
-			map[string]interface{}{
+			map[string]any{
 				"multiple": "1",
 				"single":   "3",
 			},
@@ -767,9 +767,9 @@ func TestDefaultBinder_BindToStructFromMixedSources(t *testing.T) {
 		givenURL         string
 		givenContent     io.Reader
 		givenMethod      string
-		whenBindTarget   interface{}
+		whenBindTarget   any
 		whenNoPathParams bool
-		expect           interface{}
+		expect           any
 		expectError      string
 	}{
 		{
@@ -902,7 +902,7 @@ func TestDefaultBinder_BindToStructFromMixedSources(t *testing.T) {
 				c.SetParamValues("node_from_path")
 			}
 
-			var bindTarget interface{}
+			var bindTarget any
 			if tc.whenBindTarget != nil {
 				bindTarget = tc.whenBindTarget
 			} else {
@@ -941,8 +941,8 @@ func TestDefaultBinder_BindBody(t *testing.T) {
 		givenMethod      string
 		givenContentType string
 		whenNoPathParams bool
-		whenBindTarget   interface{}
-		expect           interface{}
+		whenBindTarget   any
+		expect           any
 		expectError      string
 	}{
 		{
@@ -1083,7 +1083,7 @@ func TestDefaultBinder_BindBody(t *testing.T) {
 				c.SetParamValues("real_node")
 			}
 
-			var bindTarget interface{}
+			var bindTarget any
 			if tc.whenBindTarget != nil {
 				bindTarget = tc.whenBindTarget
 			} else {
diff --git a/binder.go b/binder.go
index da15ae82a..300c00934 100644
--- a/binder.go
+++ b/binder.go
@@ -75,7 +75,7 @@ type BindingError struct {
 }
 
 // NewBindingError creates new instance of binding error
-func NewBindingError(sourceParam string, values []string, message interface{}, internalError error) error {
+func NewBindingError(sourceParam string, values []string, message any, internalError error) error {
 	return &BindingError{
 		Field:  sourceParam,
 		Values: values,
@@ -99,7 +99,7 @@ type ValueBinder struct {
 	// ValuesFunc is used to get all values for parameter from request. i.e. `/api/search?ids=1&ids=2`
 	ValuesFunc func(sourceParam string) []string
 	// ErrorFunc is used to create errors. Allows you to use your own error type, that for example marshals to your specific json response
-	ErrorFunc func(sourceParam string, values []string, message interface{}, internalError error) error
+	ErrorFunc func(sourceParam string, values []string, message any, internalError error) error
 	errors    []error
 	// failFast is flag for binding methods to return without attempting to bind when previous binding already failed
 	failFast bool
@@ -402,17 +402,17 @@ func (b *ValueBinder) MustTextUnmarshaler(sourceParam string, dest encoding.Text
 
 // BindWithDelimiter binds parameter to destination by suitable conversion function.
 // Delimiter is used before conversion to split parameter value to separate values
-func (b *ValueBinder) BindWithDelimiter(sourceParam string, dest interface{}, delimiter string) *ValueBinder {
+func (b *ValueBinder) BindWithDelimiter(sourceParam string, dest any, delimiter string) *ValueBinder {
 	return b.bindWithDelimiter(sourceParam, dest, delimiter, false)
 }
 
 // MustBindWithDelimiter requires parameter value to exist to bind destination by suitable conversion function.
 // Delimiter is used before conversion to split parameter value to separate values
-func (b *ValueBinder) MustBindWithDelimiter(sourceParam string, dest interface{}, delimiter string) *ValueBinder {
+func (b *ValueBinder) MustBindWithDelimiter(sourceParam string, dest any, delimiter string) *ValueBinder {
 	return b.bindWithDelimiter(sourceParam, dest, delimiter, true)
 }
 
-func (b *ValueBinder) bindWithDelimiter(sourceParam string, dest interface{}, delimiter string, valueMustExist bool) *ValueBinder {
+func (b *ValueBinder) bindWithDelimiter(sourceParam string, dest any, delimiter string, valueMustExist bool) *ValueBinder {
 	if b.failFast && b.errors != nil {
 		return b
 	}
@@ -500,7 +500,7 @@ func (b *ValueBinder) MustInt(sourceParam string, dest *int) *ValueBinder {
 	return b.intValue(sourceParam, dest, 0, true)
 }
 
-func (b *ValueBinder) intValue(sourceParam string, dest interface{}, bitSize int, valueMustExist bool) *ValueBinder {
+func (b *ValueBinder) intValue(sourceParam string, dest any, bitSize int, valueMustExist bool) *ValueBinder {
 	if b.failFast && b.errors != nil {
 		return b
 	}
@@ -516,7 +516,7 @@ func (b *ValueBinder) intValue(sourceParam string, dest interface{}, bitSize int
 	return b.int(sourceParam, value, dest, bitSize)
 }
 
-func (b *ValueBinder) int(sourceParam string, value string, dest interface{}, bitSize int) *ValueBinder {
+func (b *ValueBinder) int(sourceParam string, value string, dest any, bitSize int) *ValueBinder {
 	n, err := strconv.ParseInt(value, 10, bitSize)
 	if err != nil {
 		if bitSize == 0 {
@@ -542,7 +542,7 @@ func (b *ValueBinder) int(sourceParam string, value string, dest interface{}, bi
 	return b
 }
 
-func (b *ValueBinder) intsValue(sourceParam string, dest interface{}, valueMustExist bool) *ValueBinder {
+func (b *ValueBinder) intsValue(sourceParam string, dest any, valueMustExist bool) *ValueBinder {
 	if b.failFast && b.errors != nil {
 		return b
 	}
@@ -557,7 +557,7 @@ func (b *ValueBinder) intsValue(sourceParam string, dest interface{}, valueMustE
 	return b.ints(sourceParam, values, dest)
 }
 
-func (b *ValueBinder) ints(sourceParam string, values []string, dest interface{}) *ValueBinder {
+func (b *ValueBinder) ints(sourceParam string, values []string, dest any) *ValueBinder {
 	switch d := dest.(type) {
 	case *[]int64:
 		tmp := make([]int64, len(values))
@@ -728,7 +728,7 @@ func (b *ValueBinder) MustUint(sourceParam string, dest *uint) *ValueBinder {
 	return b.uintValue(sourceParam, dest, 0, true)
 }
 
-func (b *ValueBinder) uintValue(sourceParam string, dest interface{}, bitSize int, valueMustExist bool) *ValueBinder {
+func (b *ValueBinder) uintValue(sourceParam string, dest any, bitSize int, valueMustExist bool) *ValueBinder {
 	if b.failFast && b.errors != nil {
 		return b
 	}
@@ -744,7 +744,7 @@ func (b *ValueBinder) uintValue(sourceParam string, dest interface{}, bitSize in
 	return b.uint(sourceParam, value, dest, bitSize)
 }
 
-func (b *ValueBinder) uint(sourceParam string, value string, dest interface{}, bitSize int) *ValueBinder {
+func (b *ValueBinder) uint(sourceParam string, value string, dest any, bitSize int) *ValueBinder {
 	n, err := strconv.ParseUint(value, 10, bitSize)
 	if err != nil {
 		if bitSize == 0 {
@@ -770,7 +770,7 @@ func (b *ValueBinder) uint(sourceParam string, value string, dest interface{}, b
 	return b
 }
 
-func (b *ValueBinder) uintsValue(sourceParam string, dest interface{}, valueMustExist bool) *ValueBinder {
+func (b *ValueBinder) uintsValue(sourceParam string, dest any, valueMustExist bool) *ValueBinder {
 	if b.failFast && b.errors != nil {
 		return b
 	}
@@ -785,7 +785,7 @@ func (b *ValueBinder) uintsValue(sourceParam string, dest interface{}, valueMust
 	return b.uints(sourceParam, values, dest)
 }
 
-func (b *ValueBinder) uints(sourceParam string, values []string, dest interface{}) *ValueBinder {
+func (b *ValueBinder) uints(sourceParam string, values []string, dest any) *ValueBinder {
 	switch d := dest.(type) {
 	case *[]uint64:
 		tmp := make([]uint64, len(values))
@@ -991,7 +991,7 @@ func (b *ValueBinder) MustFloat32(sourceParam string, dest *float32) *ValueBinde
 	return b.floatValue(sourceParam, dest, 32, true)
 }
 
-func (b *ValueBinder) floatValue(sourceParam string, dest interface{}, bitSize int, valueMustExist bool) *ValueBinder {
+func (b *ValueBinder) floatValue(sourceParam string, dest any, bitSize int, valueMustExist bool) *ValueBinder {
 	if b.failFast && b.errors != nil {
 		return b
 	}
@@ -1007,7 +1007,7 @@ func (b *ValueBinder) floatValue(sourceParam string, dest interface{}, bitSize i
 	return b.float(sourceParam, value, dest, bitSize)
 }
 
-func (b *ValueBinder) float(sourceParam string, value string, dest interface{}, bitSize int) *ValueBinder {
+func (b *ValueBinder) float(sourceParam string, value string, dest any, bitSize int) *ValueBinder {
 	n, err := strconv.ParseFloat(value, bitSize)
 	if err != nil {
 		b.setError(b.ErrorFunc(sourceParam, []string{value}, fmt.Sprintf("failed to bind field value to float%v", bitSize), err))
@@ -1023,7 +1023,7 @@ func (b *ValueBinder) float(sourceParam string, value string, dest interface{},
 	return b
 }
 
-func (b *ValueBinder) floatsValue(sourceParam string, dest interface{}, valueMustExist bool) *ValueBinder {
+func (b *ValueBinder) floatsValue(sourceParam string, dest any, valueMustExist bool) *ValueBinder {
 	if b.failFast && b.errors != nil {
 		return b
 	}
@@ -1038,7 +1038,7 @@ func (b *ValueBinder) floatsValue(sourceParam string, dest interface{}, valueMus
 	return b.floats(sourceParam, values, dest)
 }
 
-func (b *ValueBinder) floats(sourceParam string, values []string, dest interface{}) *ValueBinder {
+func (b *ValueBinder) floats(sourceParam string, values []string, dest any) *ValueBinder {
 	switch d := dest.(type) {
 	case *[]float64:
 		tmp := make([]float64, len(values))
diff --git a/binder_test.go b/binder_test.go
index d552b604d..7ba85ead8 100644
--- a/binder_test.go
+++ b/binder_test.go
@@ -7,7 +7,6 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"github.com/stretchr/testify/assert"
 	"io"
 	"math/big"
 	"net/http"
@@ -16,6 +15,8 @@ import (
 	"strings"
 	"testing"
 	"time"
+
+	"github.com/stretchr/testify/assert"
 )
 
 func createTestContext(URL string, body io.Reader, pathParams map[string]string) Context {
@@ -271,7 +272,7 @@ func TestValueBinder_CustomFunc(t *testing.T) {
 		givenFuncErrors   []error
 		whenURL           string
 		expectParamValues []string
-		expectValue       interface{}
+		expectValue       any
 		expectErrors      []string
 	}{
 		{
@@ -346,7 +347,7 @@ func TestValueBinder_MustCustomFunc(t *testing.T) {
 		givenFuncErrors   []error
 		whenURL           string
 		expectParamValues []string
-		expectValue       interface{}
+		expectValue       any
 		expectErrors      []string
 	}{
 		{
@@ -2376,7 +2377,7 @@ func TestValueBinder_BindWithDelimiter_types(t *testing.T) {
 	var testCases = []struct {
 		name    string
 		whenURL string
-		expect  interface{}
+		expect  any
 	}{
 		{
 			name:   "ok, strings",
diff --git a/context.go b/context.go
index f5dd5a69d..a70338d3c 100644
--- a/context.go
+++ b/context.go
@@ -97,22 +97,22 @@ type Context interface {
 	Cookies() []*http.Cookie
 
 	// Get retrieves data from the context.
-	Get(key string) interface{}
+	Get(key string) any
 
 	// Set saves data in the context.
-	Set(key string, val interface{})
+	Set(key string, val any)
 
 	// Bind binds path params, query params and the request body into provided type `i`. The default binder
 	// binds body based on Content-Type header.
-	Bind(i interface{}) error
+	Bind(i any) error
 
 	// Validate validates provided `i`. It is usually called after `Context#Bind()`.
 	// Validator must be registered using `Echo#Validator`.
-	Validate(i interface{}) error
+	Validate(i any) error
 
 	// Render renders a template with data and sends a text/html response with status
 	// code. Renderer must be registered using `Echo.Renderer`.
-	Render(code int, name string, data interface{}) error
+	Render(code int, name string, data any) error
 
 	// HTML sends an HTTP response with status code.
 	HTML(code int, html string) error
@@ -124,27 +124,27 @@ type Context interface {
 	String(code int, s string) error
 
 	// JSON sends a JSON response with status code.
-	JSON(code int, i interface{}) error
+	JSON(code int, i any) error
 
 	// JSONPretty sends a pretty-print JSON with status code.
-	JSONPretty(code int, i interface{}, indent string) error
+	JSONPretty(code int, i any, indent string) error
 
 	// JSONBlob sends a JSON blob response with status code.
 	JSONBlob(code int, b []byte) error
 
 	// JSONP sends a JSONP response with status code. It uses `callback` to construct
 	// the JSONP payload.
-	JSONP(code int, callback string, i interface{}) error
+	JSONP(code int, callback string, i any) error
 
 	// JSONPBlob sends a JSONP blob response with status code. It uses `callback`
 	// to construct the JSONP payload.
 	JSONPBlob(code int, callback string, b []byte) error
 
 	// XML sends an XML response with status code.
-	XML(code int, i interface{}) error
+	XML(code int, i any) error
 
 	// XMLPretty sends a pretty-print XML with status code.
-	XMLPretty(code int, i interface{}, indent string) error
+	XMLPretty(code int, i any, indent string) error
 
 	// XMLBlob sends an XML blob response with status code.
 	XMLBlob(code int, b []byte) error
@@ -430,13 +430,13 @@ func (c *context) Cookies() []*http.Cookie {
 	return c.request.Cookies()
 }
 
-func (c *context) Get(key string) interface{} {
+func (c *context) Get(key string) any {
 	c.lock.RLock()
 	defer c.lock.RUnlock()
 	return c.store[key]
 }
 
-func (c *context) Set(key string, val interface{}) {
+func (c *context) Set(key string, val any) {
 	c.lock.Lock()
 	defer c.lock.Unlock()
 
@@ -446,18 +446,18 @@ func (c *context) Set(key string, val interface{}) {
 	c.store[key] = val
 }
 
-func (c *context) Bind(i interface{}) error {
+func (c *context) Bind(i any) error {
 	return c.echo.Binder.Bind(i, c)
 }
 
-func (c *context) Validate(i interface{}) error {
+func (c *context) Validate(i any) error {
 	if c.echo.Validator == nil {
 		return ErrValidatorNotRegistered
 	}
 	return c.echo.Validator.Validate(i)
 }
 
-func (c *context) Render(code int, name string, data interface{}) (err error) {
+func (c *context) Render(code int, name string, data any) (err error) {
 	if c.echo.Renderer == nil {
 		return ErrRendererNotRegistered
 	}
@@ -480,7 +480,7 @@ func (c *context) String(code int, s string) (err error) {
 	return c.Blob(code, MIMETextPlainCharsetUTF8, []byte(s))
 }
 
-func (c *context) jsonPBlob(code int, callback string, i interface{}) (err error) {
+func (c *context) jsonPBlob(code int, callback string, i any) (err error) {
 	indent := ""
 	if _, pretty := c.QueryParams()["pretty"]; c.echo.Debug || pretty {
 		indent = defaultIndent
@@ -499,13 +499,13 @@ func (c *context) jsonPBlob(code int, callback string, i interface{}) (err error
 	return
 }
 
-func (c *context) json(code int, i interface{}, indent string) error {
+func (c *context) json(code int, i any, indent string) error {
 	c.writeContentType(MIMEApplicationJSON)
 	c.response.Status = code
 	return c.echo.JSONSerializer.Serialize(c, i, indent)
 }
 
-func (c *context) JSON(code int, i interface{}) (err error) {
+func (c *context) JSON(code int, i any) (err error) {
 	indent := ""
 	if _, pretty := c.QueryParams()["pretty"]; c.echo.Debug || pretty {
 		indent = defaultIndent
@@ -513,7 +513,7 @@ func (c *context) JSON(code int, i interface{}) (err error) {
 	return c.json(code, i, indent)
 }
 
-func (c *context) JSONPretty(code int, i interface{}, indent string) (err error) {
+func (c *context) JSONPretty(code int, i any, indent string) (err error) {
 	return c.json(code, i, indent)
 }
 
@@ -521,7 +521,7 @@ func (c *context) JSONBlob(code int, b []byte) (err error) {
 	return c.Blob(code, MIMEApplicationJSON, b)
 }
 
-func (c *context) JSONP(code int, callback string, i interface{}) (err error) {
+func (c *context) JSONP(code int, callback string, i any) (err error) {
 	return c.jsonPBlob(code, callback, i)
 }
 
@@ -538,7 +538,7 @@ func (c *context) JSONPBlob(code int, callback string, b []byte) (err error) {
 	return
 }
 
-func (c *context) xml(code int, i interface{}, indent string) (err error) {
+func (c *context) xml(code int, i any, indent string) (err error) {
 	c.writeContentType(MIMEApplicationXMLCharsetUTF8)
 	c.response.WriteHeader(code)
 	enc := xml.NewEncoder(c.response)
@@ -551,7 +551,7 @@ func (c *context) xml(code int, i interface{}, indent string) (err error) {
 	return enc.Encode(i)
 }
 
-func (c *context) XML(code int, i interface{}) (err error) {
+func (c *context) XML(code int, i any) (err error) {
 	indent := ""
 	if _, pretty := c.QueryParams()["pretty"]; c.echo.Debug || pretty {
 		indent = defaultIndent
@@ -559,7 +559,7 @@ func (c *context) XML(code int, i interface{}) (err error) {
 	return c.xml(code, i, indent)
 }
 
-func (c *context) XMLPretty(code int, i interface{}, indent string) (err error) {
+func (c *context) XMLPretty(code int, i any, indent string) (err error) {
 	return c.xml(code, i, indent)
 }
 
diff --git a/context_test.go b/context_test.go
index 1fd89edb4..ca1d56322 100644
--- a/context_test.go
+++ b/context_test.go
@@ -82,7 +82,7 @@ func BenchmarkRealIPForHeaderXForwardFor(b *testing.B) {
 	}
 }
 
-func (t *Template) Render(w io.Writer, name string, data interface{}, c Context) error {
+func (t *Template) Render(w io.Writer, name string, data any, c Context) error {
 	return t.templates.ExecuteTemplate(w, name, data)
 }
 
@@ -867,7 +867,7 @@ func TestContext_Path(t *testing.T) {
 
 type validator struct{}
 
-func (*validator) Validate(i interface{}) error {
+func (*validator) Validate(i any) error {
 	return nil
 }
 
diff --git a/echo.go b/echo.go
index 2d7d5bb8d..43761d309 100644
--- a/echo.go
+++ b/echo.go
@@ -116,9 +116,9 @@ type Route struct {
 
 // HTTPError represents an error that occurred while handling a request.
 type HTTPError struct {
-	Internal error       `json:"-"` // Stores the error returned by an external dependency
-	Message  interface{} `json:"message"`
-	Code     int         `json:"-"`
+	Internal error `json:"-"` // Stores the error returned by an external dependency
+	Message  any   `json:"message"`
+	Code     int   `json:"-"`
 }
 
 // MiddlewareFunc defines a function to process middleware.
@@ -132,17 +132,17 @@ type HTTPErrorHandler func(err error, c Context)
 
 // Validator is the interface that wraps the Validate function.
 type Validator interface {
-	Validate(i interface{}) error
+	Validate(i any) error
 }
 
 // JSONSerializer is the interface that encodes and decodes JSON to and from interfaces.
 type JSONSerializer interface {
-	Serialize(c Context, i interface{}, indent string) error
-	Deserialize(c Context, i interface{}) error
+	Serialize(c Context, i any, indent string) error
+	Deserialize(c Context, i any) error
 }
 
-// Map defines a generic map of type `map[string]interface{}`.
-type Map map[string]interface{}
+// Map defines a generic map of type `map[string]any`.
+type Map map[string]any
 
 // Common struct for Echo & Group.
 type common struct{}
@@ -378,7 +378,7 @@ func New() (e *Echo) {
 	e.JSONSerializer = &DefaultJSONSerializer{}
 	e.Logger.SetLevel(log.ERROR)
 	e.StdLogger = stdLog.New(e.Logger.Output(), e.Logger.Prefix()+": ", 0)
-	e.pool.New = func() interface{} {
+	e.pool.New = func() any {
 		return e.NewContext(nil, nil)
 	}
 	e.router = NewRouter(e)
@@ -610,18 +610,18 @@ func (e *Echo) Group(prefix string, m ...MiddlewareFunc) (g *Group) {
 }
 
 // URI generates an URI from handler.
-func (e *Echo) URI(handler HandlerFunc, params ...interface{}) string {
+func (e *Echo) URI(handler HandlerFunc, params ...any) string {
 	name := handlerName(handler)
 	return e.Reverse(name, params...)
 }
 
 // URL is an alias for `URI` function.
-func (e *Echo) URL(h HandlerFunc, params ...interface{}) string {
+func (e *Echo) URL(h HandlerFunc, params ...any) string {
 	return e.URI(h, params...)
 }
 
 // Reverse generates a URL from route name and provided parameters.
-func (e *Echo) Reverse(name string, params ...interface{}) string {
+func (e *Echo) Reverse(name string, params ...any) string {
 	return e.router.Reverse(name, params...)
 }
 
@@ -688,7 +688,7 @@ func (e *Echo) Start(address string) error {
 // StartTLS starts an HTTPS server.
 // If `certFile` or `keyFile` is `string` the values are treated as file paths.
 // If `certFile` or `keyFile` is `[]byte` the values are treated as the certificate or key as-is.
-func (e *Echo) StartTLS(address string, certFile, keyFile interface{}) (err error) {
+func (e *Echo) StartTLS(address string, certFile, keyFile any) (err error) {
 	e.startupMutex.Lock()
 	var cert []byte
 	if cert, err = filepathOrContent(certFile); err != nil {
@@ -719,7 +719,7 @@ func (e *Echo) StartTLS(address string, certFile, keyFile interface{}) (err erro
 	return s.Serve(e.TLSListener)
 }
 
-func filepathOrContent(fileOrContent interface{}) (content []byte, err error) {
+func filepathOrContent(fileOrContent any) (content []byte, err error) {
 	switch v := fileOrContent.(type) {
 	case string:
 		return os.ReadFile(v)
@@ -884,7 +884,7 @@ func (e *Echo) Shutdown(ctx stdContext.Context) error {
 }
 
 // NewHTTPError creates a new HTTPError instance.
-func NewHTTPError(code int, message ...interface{}) *HTTPError {
+func NewHTTPError(code int, message ...any) *HTTPError {
 	he := &HTTPError{Code: code, Message: http.StatusText(code)}
 	if len(message) > 0 {
 		he.Message = message[0]
diff --git a/echo_test.go b/echo_test.go
index b7f32017a..08cc7162b 100644
--- a/echo_test.go
+++ b/echo_test.go
@@ -812,7 +812,7 @@ func TestEcho_RouteNotFound(t *testing.T) {
 	var testCases = []struct {
 		name        string
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectCode  int
 	}{
 		{
@@ -1075,8 +1075,8 @@ func TestEchoStartTLSByteString(t *testing.T) {
 	require.NoError(t, err)
 
 	testCases := []struct {
-		cert        interface{}
-		key         interface{}
+		cert        any
+		key         any
 		expectedErr error
 		name        string
 	}{
@@ -1222,7 +1222,7 @@ func testMethod(t *testing.T, method, path string, e *Echo) {
 	h := reflect.ValueOf(func(c Context) error {
 		return c.String(http.StatusOK, method)
 	})
-	i := interface{}(e)
+	i := any(e)
 	reflect.ValueOf(i).MethodByName(method).Call([]reflect.Value{p, h})
 	_, body := request(method, path, e)
 	assert.Equal(t, method, body)
@@ -1237,7 +1237,7 @@ func request(method, path string, e *Echo) (int, string) {
 
 func TestHTTPError(t *testing.T) {
 	t.Run("non-internal", func(t *testing.T) {
-		err := NewHTTPError(http.StatusBadRequest, map[string]interface{}{
+		err := NewHTTPError(http.StatusBadRequest, map[string]any{
 			"code": 12,
 		})
 
@@ -1245,7 +1245,7 @@ func TestHTTPError(t *testing.T) {
 	})
 
 	t.Run("internal and SetInternal", func(t *testing.T) {
-		err := NewHTTPError(http.StatusBadRequest, map[string]interface{}{
+		err := NewHTTPError(http.StatusBadRequest, map[string]any{
 			"code": 12,
 		})
 		err.SetInternal(errors.New("internal error"))
@@ -1253,7 +1253,7 @@ func TestHTTPError(t *testing.T) {
 	})
 
 	t.Run("internal and WithInternal", func(t *testing.T) {
-		err := NewHTTPError(http.StatusBadRequest, map[string]interface{}{
+		err := NewHTTPError(http.StatusBadRequest, map[string]any{
 			"code": 12,
 		})
 		err = err.WithInternal(errors.New("internal error"))
@@ -1263,7 +1263,7 @@ func TestHTTPError(t *testing.T) {
 
 func TestHTTPError_Unwrap(t *testing.T) {
 	t.Run("non-internal", func(t *testing.T) {
-		err := NewHTTPError(http.StatusBadRequest, map[string]interface{}{
+		err := NewHTTPError(http.StatusBadRequest, map[string]any{
 			"code": 12,
 		})
 
@@ -1271,7 +1271,7 @@ func TestHTTPError_Unwrap(t *testing.T) {
 	})
 
 	t.Run("unwrap internal and SetInternal", func(t *testing.T) {
-		err := NewHTTPError(http.StatusBadRequest, map[string]interface{}{
+		err := NewHTTPError(http.StatusBadRequest, map[string]any{
 			"code": 12,
 		})
 		err.SetInternal(errors.New("internal error"))
@@ -1279,7 +1279,7 @@ func TestHTTPError_Unwrap(t *testing.T) {
 	})
 
 	t.Run("unwrap internal and WithInternal", func(t *testing.T) {
-		err := NewHTTPError(http.StatusBadRequest, map[string]interface{}{
+		err := NewHTTPError(http.StatusBadRequest, map[string]any{
 			"code": 12,
 		})
 		err = err.WithInternal(errors.New("internal error"))
@@ -1387,7 +1387,7 @@ func TestDefaultHTTPErrorHandler(t *testing.T) {
 			})
 
 			e.Any("/servererror", func(c Context) error { // complex errors are serialized to pretty JSON
-				return NewHTTPError(http.StatusInternalServerError, map[string]interface{}{
+				return NewHTTPError(http.StatusInternalServerError, map[string]any{
 					"code":    33,
 					"message": "Something bad happened",
 					"error":   "stackinfo",
@@ -1595,7 +1595,7 @@ func TestEchoReverse(t *testing.T) {
 	var testCases = []struct {
 		name          string
 		whenRouteName string
-		whenParams    []interface{}
+		whenParams    []any
 		expect        string
 	}{
 		{
@@ -1611,7 +1611,7 @@ func TestEchoReverse(t *testing.T) {
 		{
 			name:          "ok,static with non existent param",
 			whenRouteName: "/static",
-			whenParams:    []interface{}{"missing param"},
+			whenParams:    []any{"missing param"},
 			expect:        "/static",
 		},
 		{
@@ -1622,7 +1622,7 @@ func TestEchoReverse(t *testing.T) {
 		{
 			name:          "ok, wildcard with params",
 			whenRouteName: "/static/*",
-			whenParams:    []interface{}{"foo.txt"},
+			whenParams:    []any{"foo.txt"},
 			expect:        "/static/foo.txt",
 		},
 		{
@@ -1633,7 +1633,7 @@ func TestEchoReverse(t *testing.T) {
 		{
 			name:          "ok, single param with param",
 			whenRouteName: "/params/:foo",
-			whenParams:    []interface{}{"one"},
+			whenParams:    []any{"one"},
 			expect:        "/params/one",
 		},
 		{
@@ -1644,31 +1644,31 @@ func TestEchoReverse(t *testing.T) {
 		{
 			name:          "ok, multi param with one param",
 			whenRouteName: "/params/:foo/bar/:qux",
-			whenParams:    []interface{}{"one"},
+			whenParams:    []any{"one"},
 			expect:        "/params/one/bar/:qux",
 		},
 		{
 			name:          "ok, multi param with all params",
 			whenRouteName: "/params/:foo/bar/:qux",
-			whenParams:    []interface{}{"one", "two"},
+			whenParams:    []any{"one", "two"},
 			expect:        "/params/one/bar/two",
 		},
 		{
 			name:          "ok, multi param + wildcard with all params",
 			whenRouteName: "/params/:foo/bar/:qux/*",
-			whenParams:    []interface{}{"one", "two", "three"},
+			whenParams:    []any{"one", "two", "three"},
 			expect:        "/params/one/bar/two/three",
 		},
 		{
 			name:          "ok, backslash is not escaped",
 			whenRouteName: "/backslash",
-			whenParams:    []interface{}{"test"},
+			whenParams:    []any{"test"},
 			expect:        `/a\b/test`,
 		},
 		{
 			name:          "ok, escaped colon verbs",
 			whenRouteName: "/params:customVerb",
-			whenParams:    []interface{}{"PATCH"},
+			whenParams:    []any{"PATCH"},
 			expect:        `/params:PATCH`,
 		},
 	}
diff --git a/group_test.go b/group_test.go
index a97371418..78c2ed485 100644
--- a/group_test.go
+++ b/group_test.go
@@ -127,7 +127,7 @@ func TestGroup_RouteNotFound(t *testing.T) {
 	var testCases = []struct {
 		name        string
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectCode  int
 	}{
 		{
@@ -193,7 +193,7 @@ func TestGroup_RouteNotFoundWithMiddleware(t *testing.T) {
 		name           string
 		givenCustom404 bool
 		whenURL        string
-		expectBody     interface{}
+		expectBody     any
 		expectCode     int
 	}{
 		{
diff --git a/json.go b/json.go
index 6da0aaf97..589cda55f 100644
--- a/json.go
+++ b/json.go
@@ -14,7 +14,7 @@ type DefaultJSONSerializer struct{}
 
 // Serialize converts an interface into a json and writes it to the response.
 // You can optionally use the indent parameter to produce pretty JSONs.
-func (d DefaultJSONSerializer) Serialize(c Context, i interface{}, indent string) error {
+func (d DefaultJSONSerializer) Serialize(c Context, i any, indent string) error {
 	enc := json.NewEncoder(c.Response())
 	if indent != "" {
 		enc.SetIndent("", indent)
@@ -23,7 +23,7 @@ func (d DefaultJSONSerializer) Serialize(c Context, i interface{}, indent string
 }
 
 // Deserialize reads a JSON from a request body and converts it into an interface.
-func (d DefaultJSONSerializer) Deserialize(c Context, i interface{}) error {
+func (d DefaultJSONSerializer) Deserialize(c Context, i any) error {
 	err := json.NewDecoder(c.Request().Body).Decode(i)
 	if ute, ok := err.(*json.UnmarshalTypeError); ok {
 		return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unmarshal type error: expected=%v, got=%v, field=%v, offset=%v", ute.Type, ute.Value, ute.Field, ute.Offset)).SetInternal(err)
diff --git a/log.go b/log.go
index 0acd9ff03..2a7743b6c 100644
--- a/log.go
+++ b/log.go
@@ -4,8 +4,9 @@
 package echo
 
 import (
-	"github.com/labstack/gommon/log"
 	"io"
+
+	"github.com/labstack/gommon/log"
 )
 
 // Logger defines the logging interface.
@@ -17,25 +18,25 @@ type Logger interface {
 	Level() log.Lvl
 	SetLevel(v log.Lvl)
 	SetHeader(h string)
-	Print(i ...interface{})
-	Printf(format string, args ...interface{})
+	Print(i ...any)
+	Printf(format string, args ...any)
 	Printj(j log.JSON)
-	Debug(i ...interface{})
-	Debugf(format string, args ...interface{})
+	Debug(i ...any)
+	Debugf(format string, args ...any)
 	Debugj(j log.JSON)
-	Info(i ...interface{})
-	Infof(format string, args ...interface{})
+	Info(i ...any)
+	Infof(format string, args ...any)
 	Infoj(j log.JSON)
-	Warn(i ...interface{})
-	Warnf(format string, args ...interface{})
+	Warn(i ...any)
+	Warnf(format string, args ...any)
 	Warnj(j log.JSON)
-	Error(i ...interface{})
-	Errorf(format string, args ...interface{})
+	Error(i ...any)
+	Errorf(format string, args ...any)
 	Errorj(j log.JSON)
-	Fatal(i ...interface{})
+	Fatal(i ...any)
 	Fatalj(j log.JSON)
-	Fatalf(format string, args ...interface{})
-	Panic(i ...interface{})
+	Fatalf(format string, args ...any)
+	Panic(i ...any)
 	Panicj(j log.JSON)
-	Panicf(format string, args ...interface{})
+	Panicf(format string, args ...any)
 }
diff --git a/middleware/body_limit.go b/middleware/body_limit.go
index 7d3c665f2..c1c3cd407 100644
--- a/middleware/body_limit.go
+++ b/middleware/body_limit.go
@@ -107,7 +107,7 @@ func (r *limitedReader) Reset(reader io.ReadCloser) {
 
 func limitedReaderPool(c BodyLimitConfig) sync.Pool {
 	return sync.Pool{
-		New: func() interface{} {
+		New: func() any {
 			return &limitedReader{BodyLimitConfig: c}
 		},
 	}
diff --git a/middleware/compress.go b/middleware/compress.go
index 012b76b01..eaacb6a7e 100644
--- a/middleware/compress.go
+++ b/middleware/compress.go
@@ -210,7 +210,7 @@ func (w *gzipResponseWriter) Push(target string, opts *http.PushOptions) error {
 
 func gzipCompressPool(config GzipConfig) sync.Pool {
 	return sync.Pool{
-		New: func() interface{} {
+		New: func() any {
 			w, err := gzip.NewWriterLevel(io.Discard, config.Level)
 			if err != nil {
 				return err
@@ -222,7 +222,7 @@ func gzipCompressPool(config GzipConfig) sync.Pool {
 
 func bufferPool() sync.Pool {
 	return sync.Pool{
-		New: func() interface{} {
+		New: func() any {
 			b := &bytes.Buffer{}
 			return b
 		},
diff --git a/middleware/decompress.go b/middleware/decompress.go
index 0c56176ee..8c418efd7 100644
--- a/middleware/decompress.go
+++ b/middleware/decompress.go
@@ -40,7 +40,7 @@ type DefaultGzipDecompressPool struct {
 }
 
 func (d *DefaultGzipDecompressPool) gzipDecompressPool() sync.Pool {
-	return sync.Pool{New: func() interface{} { return new(gzip.Reader) }}
+	return sync.Pool{New: func() any { return new(gzip.Reader) }}
 }
 
 // Decompress decompresses request body based if content encoding type is set to "gzip" with default config
diff --git a/middleware/decompress_test.go b/middleware/decompress_test.go
index 63b1a68f5..52506ce8e 100644
--- a/middleware/decompress_test.go
+++ b/middleware/decompress_test.go
@@ -145,7 +145,7 @@ type TestDecompressPoolWithError struct {
 
 func (d *TestDecompressPoolWithError) gzipDecompressPool() sync.Pool {
 	return sync.Pool{
-		New: func() interface{} {
+		New: func() any {
 			return errors.New("pool error")
 		},
 	}
diff --git a/middleware/jwt.go b/middleware/jwt.go
index a6bf16f95..0fce2e505 100644
--- a/middleware/jwt.go
+++ b/middleware/jwt.go
@@ -9,10 +9,11 @@ package middleware
 import (
 	"errors"
 	"fmt"
-	"github.com/golang-jwt/jwt"
-	"github.com/labstack/echo/v4"
 	"net/http"
 	"reflect"
+
+	"github.com/golang-jwt/jwt"
+	"github.com/labstack/echo/v4"
 )
 
 // JWTConfig defines the config for JWT middleware.
@@ -45,13 +46,13 @@ type JWTConfig struct {
 	// This is one of the three options to provide a token validation key.
 	// The order of precedence is a user-defined KeyFunc, SigningKeys and SigningKey.
 	// Required if neither user-defined KeyFunc nor SigningKeys is provided.
-	SigningKey interface{}
+	SigningKey any
 
 	// Map of signing keys to validate token with kid field usage.
 	// This is one of the three options to provide a token validation key.
 	// The order of precedence is a user-defined KeyFunc, SigningKeys and SigningKey.
 	// Required if neither user-defined KeyFunc nor SigningKey is provided.
-	SigningKeys map[string]interface{}
+	SigningKeys map[string]any
 
 	// Signing method used to check the token's signing algorithm.
 	// Optional. Default value HS256.
@@ -110,7 +111,7 @@ type JWTConfig struct {
 	// ParseTokenFunc defines a user-defined function that parses token from given auth. Returns an error when token
 	// parsing fails or parsed token is invalid.
 	// Defaults to implementation using `github.com/golang-jwt/jwt` as JWT implementation library
-	ParseTokenFunc func(auth string, c echo.Context) (interface{}, error)
+	ParseTokenFunc func(auth string, c echo.Context) (any, error)
 }
 
 // JWTSuccessHandler defines a function which is executed for a valid token.
@@ -155,7 +156,7 @@ var DefaultJWTConfig = JWTConfig{
 // See `JWTConfig.TokenLookup`
 //
 // Deprecated: Please use https://github.com/labstack/echo-jwt instead
-func JWT(key interface{}) echo.MiddlewareFunc {
+func JWT(key any) echo.MiddlewareFunc {
 	c := DefaultJWTConfig
 	c.SigningKey = key
 	return JWTWithConfig(c)
@@ -264,7 +265,7 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
 	}
 }
 
-func (config *JWTConfig) defaultParseToken(auth string, c echo.Context) (interface{}, error) {
+func (config *JWTConfig) defaultParseToken(auth string, c echo.Context) (any, error) {
 	var token *jwt.Token
 	var err error
 	// Issue #647, #656
@@ -285,7 +286,7 @@ func (config *JWTConfig) defaultParseToken(auth string, c echo.Context) (interfa
 }
 
 // defaultKeyFunc returns a signing key of the given token.
-func (config *JWTConfig) defaultKeyFunc(t *jwt.Token) (interface{}, error) {
+func (config *JWTConfig) defaultKeyFunc(t *jwt.Token) (any, error) {
 	// Check the signing method
 	if t.Method.Alg() != config.SigningMethod {
 		return nil, fmt.Errorf("unexpected jwt signing method=%v", t.Header["alg"])
diff --git a/middleware/jwt_test.go b/middleware/jwt_test.go
index bbe4b8808..736368ebc 100644
--- a/middleware/jwt_test.go
+++ b/middleware/jwt_test.go
@@ -259,7 +259,7 @@ func TestJWTConfig(t *testing.T) {
 			name:    "Valid JWT with a valid key using a user-defined KeyFunc",
 			hdrAuth: validAuth,
 			config: JWTConfig{
-				KeyFunc: func(*jwt.Token) (interface{}, error) {
+				KeyFunc: func(*jwt.Token) (any, error) {
 					return validKey, nil
 				},
 			},
@@ -268,7 +268,7 @@ func TestJWTConfig(t *testing.T) {
 			name:    "Valid JWT with an invalid key using a user-defined KeyFunc",
 			hdrAuth: validAuth,
 			config: JWTConfig{
-				KeyFunc: func(*jwt.Token) (interface{}, error) {
+				KeyFunc: func(*jwt.Token) (any, error) {
 					return invalidKey, nil
 				},
 			},
@@ -278,7 +278,7 @@ func TestJWTConfig(t *testing.T) {
 			name:    "Token verification does not pass using a user-defined KeyFunc",
 			hdrAuth: validAuth,
 			config: JWTConfig{
-				KeyFunc: func(*jwt.Token) (interface{}, error) {
+				KeyFunc: func(*jwt.Token) (any, error) {
 					return nil, errors.New("faulty KeyFunc")
 				},
 			},
@@ -359,8 +359,8 @@ func TestJWTwithKID(t *testing.T) {
 	secondToken := "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6InNlY29uZE9uZSJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.sdghDYQ85jdh0hgQ6bKbMguLI_NSPYWjkhVJkee-yZM"
 	wrongToken := "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6InNlY29uZE9uZSJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.RyhLybtVLpoewF6nz9YN79oXo32kAtgUxp8FNwTkb90"
 	staticToken := "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.1_-XFYUPpJfgsaGwYhgZEt7hfySMg-a3GN-nfZmbW7o"
-	validKeys := map[string]interface{}{"firstOne": []byte("first_secret"), "secondOne": []byte("second_secret")}
-	invalidKeys := map[string]interface{}{"thirdOne": []byte("third_secret")}
+	validKeys := map[string]any{"firstOne": []byte("first_secret"), "secondOne": []byte("second_secret")}
+	invalidKeys := map[string]any{"thirdOne": []byte("third_secret")}
 	staticSecret := []byte("static_secret")
 	invalidStaticSecret := []byte("invalid_secret")
 
@@ -569,7 +569,7 @@ func TestJWTConfig_parseTokenErrorHandling(t *testing.T) {
 
 			config := tc.given
 			parseTokenCalled := false
-			config.ParseTokenFunc = func(auth string, c echo.Context) (interface{}, error) {
+			config.ParseTokenFunc = func(auth string, c echo.Context) (any, error) {
 				parseTokenCalled = true
 				return nil, errors.New("parsing failed")
 			}
@@ -599,8 +599,8 @@ func TestJWTConfig_custom_ParseTokenFunc_Keyfunc(t *testing.T) {
 	signingKey := []byte("secret")
 
 	config := JWTConfig{
-		ParseTokenFunc: func(auth string, c echo.Context) (interface{}, error) {
-			keyFunc := func(t *jwt.Token) (interface{}, error) {
+		ParseTokenFunc: func(auth string, c echo.Context) (any, error) {
+			keyFunc := func(t *jwt.Token) (any, error) {
 				if t.Method.Alg() != "HS256" {
 					return nil, fmt.Errorf("unexpected jwt signing method=%v", t.Header["alg"])
 				}
diff --git a/middleware/logger.go b/middleware/logger.go
index 910fce8cf..bb1d86ae4 100644
--- a/middleware/logger.go
+++ b/middleware/logger.go
@@ -108,7 +108,7 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc {
 	config.colorer = color.New()
 	config.colorer.SetOutput(config.Output)
 	config.pool = &sync.Pool{
-		New: func() interface{} {
+		New: func() any {
 			return bytes.NewBuffer(make([]byte, 256))
 		},
 	}
diff --git a/middleware/static.go b/middleware/static.go
index 1016f1b09..f175375a1 100644
--- a/middleware/static.go
+++ b/middleware/static.go
@@ -255,7 +255,7 @@ func listDir(t *template.Template, name string, dir http.File, res *echo.Respons
 	res.Header().Set(echo.HeaderContentType, echo.MIMETextHTMLCharsetUTF8)
 	data := struct {
 		Name  string
-		Files []interface{}
+		Files []any
 	}{
 		Name: name,
 	}
diff --git a/middleware/util.go b/middleware/util.go
index 09428eb0b..aecad2eac 100644
--- a/middleware/util.go
+++ b/middleware/util.go
@@ -61,7 +61,7 @@ func matchSubdomain(domain, pattern string) bool {
 }
 
 // https://tip.golang.org/doc/go1.19#:~:text=Read%20no%20longer%20buffers%20random%20data%20obtained%20from%20the%20operating%20system%20between%20calls
-var randomReaderPool = sync.Pool{New: func() interface{} {
+var randomReaderPool = sync.Pool{New: func() any {
 	return bufio.NewReader(rand.Reader)
 }}
 
diff --git a/renderer.go b/renderer.go
index 44e038f35..dc75e92f5 100644
--- a/renderer.go
+++ b/renderer.go
@@ -4,7 +4,7 @@ import "io"
 
 // Renderer is the interface that wraps the Render function.
 type Renderer interface {
-	Render(io.Writer, string, interface{}, Context) error
+	Render(io.Writer, string, any, Context) error
 }
 
 // TemplateRenderer is helper to ease creating renderers for `html/template` and `text/template` packages.
@@ -24,6 +24,6 @@ type TemplateRenderer struct {
 }
 
 // Render renders the template with given data.
-func (t *TemplateRenderer) Render(w io.Writer, name string, data interface{}, c Context) error {
+func (t *TemplateRenderer) Render(w io.Writer, name string, data any, c Context) error {
 	return t.Template.ExecuteTemplate(w, name, data)
 }
diff --git a/router.go b/router.go
index 49b56966d..a32769ff4 100644
--- a/router.go
+++ b/router.go
@@ -156,7 +156,7 @@ func (r *Router) Routes() []*Route {
 }
 
 // Reverse generates a URL from route name and provided parameters.
-func (r *Router) Reverse(name string, params ...interface{}) string {
+func (r *Router) Reverse(name string, params ...any) string {
 	uri := new(bytes.Buffer)
 	ln := len(params)
 	n := 0
diff --git a/router_test.go b/router_test.go
index dca0d47bc..ec8b20015 100644
--- a/router_test.go
+++ b/router_test.go
@@ -698,7 +698,7 @@ func TestRouterParam(t *testing.T) {
 	var testCases = []struct {
 		name        string
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 	}{
 		{
@@ -804,7 +804,7 @@ func TestMethodNotAllowedAndNotFound(t *testing.T) {
 		name              string
 		whenMethod        string
 		whenURL           string
-		expectRoute       interface{}
+		expectRoute       any
 		expectParam       map[string]string
 		expectError       error
 		expectAllowHeader string
@@ -864,7 +864,7 @@ func TestMethodNotAllowedAndNotFound(t *testing.T) {
 func TestRouterOptionsMethodHandler(t *testing.T) {
 	e := New()
 
-	var keyInContext interface{}
+	var keyInContext any
 	e.Use(func(next HandlerFunc) HandlerFunc {
 		return func(c Context) error {
 			err := next(c)
@@ -952,7 +952,7 @@ func TestRouteMultiLevelBacktracking(t *testing.T) {
 	var testCases = []struct {
 		name        string
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 	}{
 		{
@@ -1184,7 +1184,7 @@ func TestNotFoundRouteAnyKind(t *testing.T) {
 	var testCases = []struct {
 		name        string
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectID    int
 		expectParam map[string]string
 	}{
@@ -1251,7 +1251,7 @@ func TestNotFoundRouteParamKind(t *testing.T) {
 	var testCases = []struct {
 		name        string
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectID    int
 		expectParam map[string]string
 	}{
@@ -1319,7 +1319,7 @@ func TestNotFoundRouteStaticKind(t *testing.T) {
 	var testCases = []struct {
 		name        string
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectID    int
 		expectParam map[string]string
 	}{
@@ -1418,7 +1418,7 @@ func TestRouterParamStaticConflict(t *testing.T) {
 
 	var testCases = []struct {
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 	}{
 		{
@@ -1461,7 +1461,7 @@ func TestRouterParam_escapeColon(t *testing.T) {
 
 	var testCases = []struct {
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 		expectError string
 	}{
@@ -1524,7 +1524,7 @@ func TestRouterMatchAny(t *testing.T) {
 
 	var testCases = []struct {
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 	}{
 		{
@@ -1605,7 +1605,7 @@ func TestRouterMatchAnyPrefixIssue(t *testing.T) {
 
 	var testCases = []struct {
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 	}{
 		{
@@ -1667,7 +1667,7 @@ func TestRouterMatchAnySlash(t *testing.T) {
 
 	var testCases = []struct {
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 		expectError error
 	}{
@@ -1752,7 +1752,7 @@ func TestRouterMatchAnyMultiLevel(t *testing.T) {
 
 	var testCases = []struct {
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 		expectError error
 	}{
@@ -1825,7 +1825,7 @@ func TestRouterMatchAnyMultiLevelWithPost(t *testing.T) {
 	var testCases = []struct {
 		whenMethod  string
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 		expectError error
 	}{
@@ -1918,7 +1918,7 @@ func TestRouterMultiRoute(t *testing.T) {
 	var testCases = []struct {
 		whenMethod  string
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 		expectError error
 	}{
@@ -1982,7 +1982,7 @@ func TestRouterPriority(t *testing.T) {
 	var testCases = []struct {
 		whenMethod  string
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 		expectError error
 	}{
@@ -2101,7 +2101,7 @@ func TestRouterPriorityNotFound(t *testing.T) {
 	var testCases = []struct {
 		whenMethod  string
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 		expectError error
 	}{
@@ -2156,7 +2156,7 @@ func TestRouterParamNames(t *testing.T) {
 	var testCases = []struct {
 		whenMethod  string
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 		expectError error
 	}{
@@ -2218,7 +2218,7 @@ func TestRouterStaticDynamicConflict(t *testing.T) {
 	var testCases = []struct {
 		whenMethod  string
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 		expectError error
 	}{
@@ -2295,7 +2295,7 @@ func TestRouterParamBacktraceNotFound(t *testing.T) {
 		name        string
 		whenMethod  string
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 		expectError error
 	}{
@@ -2449,7 +2449,7 @@ func TestRouterParam1466(t *testing.T) {
 
 	var testCases = []struct {
 		whenURL     string
-		expectRoute interface{}
+		expectRoute any
 		expectParam map[string]string
 	}{
 		{
@@ -2573,7 +2573,7 @@ func TestRouterPanicWhenParamNoRootOnlyChildsFailsFind(t *testing.T) {
 
 	var testCases = []struct {
 		whenURL      string
-		expectRoute  interface{}
+		expectRoute  any
 		expectParam  map[string]string
 		expectStatus int
 	}{