diff --git a/build/openresty/patches/ngx_lua-0.10.26_07-fix-ngx-recreate-request-issue-for-balancer-body-modified-case.patch b/build/openresty/patches/ngx_lua-0.10.26_07-fix-ngx-recreate-request-issue-for-balancer-body-modified-case.patch
new file mode 100644
index 000000000000..5489b6dff48f
--- /dev/null
+++ b/build/openresty/patches/ngx_lua-0.10.26_07-fix-ngx-recreate-request-issue-for-balancer-body-modified-case.patch
@@ -0,0 +1,93 @@
+diff --git a/bundle/ngx_lua-0.10.26/README.markdown b/bundle/ngx_lua-0.10.26/README.markdown
+index d6ec8c9..27f3880 100644
+--- a/bundle/ngx_lua-0.10.26/README.markdown
++++ b/bundle/ngx_lua-0.10.26/README.markdown
+@@ -5512,6 +5512,8 @@ If the request body has been read into memory, try calling the [ngx.req.get_body
+
+ To force in-file request bodies, try turning on [client_body_in_file_only](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_in_file_only).
+
++Note that this function is also work for balancer phase but it needs to call [balancer.recreate_request](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md#recreate_request) to make the change take effect after set the request body data or headers.
++
+ This function was first introduced in the `v0.3.1rc17` release.
+
+ See also [ngx.req.get_body_data](#ngxreqget_body_data).
+@@ -5523,7 +5525,7 @@ ngx.req.set_body_data
+
+ **syntax:** *ngx.req.set_body_data(data)*
+
+-**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua**
++**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, balancer_by_lua*,*
+
+ Set the current request's request body using the in-memory data specified by the `data` argument.
+
+@@ -5531,6 +5533,8 @@ If the request body has not been read yet, call [ngx.req.read_body](#ngxreqread_
+
+ Whether the previous request body has been read into memory or buffered into a disk file, it will be freed or the disk file will be cleaned up immediately, respectively.
+
++Note that this function is also work for balancer phase but it needs to call [balancer.recreate_request](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md#recreate_request) to make the change take effect after set the request body data or headers.
++
+ This function was first introduced in the `v0.3.1rc18` release.
+
+ See also [ngx.req.set_body_file](#ngxreqset_body_file).
+@@ -5542,7 +5546,7 @@ ngx.req.set_body_file
+
+ **syntax:** *ngx.req.set_body_file(file_name, auto_clean?)*
+
+-**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua**
++**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, balancer_by_lua*,*
+
+ Set the current request's request body using the in-file data specified by the `file_name` argument.
+
+diff --git a/bundle/ngx_lua-0.10.26/doc/HttpLuaModule.wiki b/bundle/ngx_lua-0.10.26/doc/HttpLuaModule.wiki
+index 305626c..51807c7 100644
+--- a/bundle/ngx_lua-0.10.26/doc/HttpLuaModule.wiki
++++ b/bundle/ngx_lua-0.10.26/doc/HttpLuaModule.wiki
+@@ -4637,7 +4637,7 @@ See also [[#ngx.req.get_body_data|ngx.req.get_body_data]].
+
+ '''syntax:''' ''ngx.req.set_body_data(data)''
+
+-'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*''
++'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, balancer_by_lua*''
+
+ Set the current request's request body using the in-memory data specified by the data
argument.
+
+@@ -4645,6 +4645,8 @@ If the request body has not been read yet, call [[#ngx.req.read_body|ngx.req.rea
+
+ Whether the previous request body has been read into memory or buffered into a disk file, it will be freed or the disk file will be cleaned up immediately, respectively.
+
++Note that this function is also work for balancer phase but it needs to call [https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md#recreate_request balancer.recreate_request] to make the change take effect after set the request body data or headers.
++
+ This function was first introduced in the v0.3.1rc18
release.
+
+ See also [[#ngx.req.set_body_file|ngx.req.set_body_file]].
+@@ -4653,7 +4655,7 @@ See also [[#ngx.req.set_body_file|ngx.req.set_body_file]].
+
+ '''syntax:''' ''ngx.req.set_body_file(file_name, auto_clean?)''
+
+-'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*''
++'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, balancer_by_lua*''
+
+ Set the current request's request body using the in-file data specified by the file_name
argument.
+
+@@ -4665,6 +4667,8 @@ Please ensure that the file specified by the file_name
argument exi
+
+ Whether the previous request body has been read into memory or buffered into a disk file, it will be freed or the disk file will be cleaned up immediately, respectively.
+
++Note that this function is also work for balancer phase but it needs to call [https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md#recreate_request balancer.recreate_request] to make the change take effect after set the request body data or headers.
++
+ This function was first introduced in the v0.3.1rc18
release.
+
+ See also [[#ngx.req.set_body_data|ngx.req.set_body_data]].
+diff --git a/bundle/ngx_lua-0.10.26/src/ngx_http_lua_balancer.c b/bundle/ngx_lua-0.10.26/src/ngx_http_lua_balancer.c
+index af4da73..4da4393 100644
+--- a/bundle/ngx_lua-0.10.26/src/ngx_http_lua_balancer.c
++++ b/bundle/ngx_lua-0.10.26/src/ngx_http_lua_balancer.c
+@@ -802,7 +802,7 @@ ngx_http_lua_ffi_balancer_recreate_request(ngx_http_request_t *r,
+ /* u->request_bufs already contains a valid request buffer
+ * remove it from chain first
+ */
+- u->request_bufs = u->request_bufs->next;
++ u->request_bufs = r->request_body->bufs;
+ }
+
+ return u->create_request(r);
diff --git a/changelog/unreleased/kong/fix-ngx-balancer-recreate-request-api-for-balancer-body-refresh.yml b/changelog/unreleased/kong/fix-ngx-balancer-recreate-request-api-for-balancer-body-refresh.yml
new file mode 100644
index 000000000000..60feef4f233f
--- /dev/null
+++ b/changelog/unreleased/kong/fix-ngx-balancer-recreate-request-api-for-balancer-body-refresh.yml
@@ -0,0 +1,4 @@
+message: |
+ **Core**: Fixed an issue where `ngx.balancer.recreate_request` API does not refresh body buffer when `ngx.req.set_body_data` is used in balancer phase
+type: bugfix
+scope: Core
diff --git a/t/04-patch/04-fix-ngx-recreate-request-work-for-body.t b/t/04-patch/04-fix-ngx-recreate-request-work-for-body.t
new file mode 100644
index 000000000000..697f36ef3da1
--- /dev/null
+++ b/t/04-patch/04-fix-ngx-recreate-request-work-for-body.t
@@ -0,0 +1,57 @@
+# vim:set ft= ts=4 sw=4 et fdm=marker:
+
+use Test::Nginx::Socket::Lua;
+
+#worker_connections(1014);
+#master_on();
+#workers(2);
+#log_level('warn');
+
+repeat_each(2);
+#repeat_each(1);
+
+plan tests => repeat_each() * (blocks() * 2);
+
+#no_diff();
+#no_long_string();
+run_tests();
+
+__DATA__
+=== TEST 1: recreate_request refresh body buffer when ngx.req.set_body_data is used in balancer phase
+--- http_config
+ lua_package_path "../lua-resty-core/lib/?.lua;;";
+
+ server {
+ listen 127.0.0.1:$TEST_NGINX_RAND_PORT_1;
+
+ location / {
+ content_by_lua_block {
+ ngx.req.read_body()
+ local body = ngx.req.get_body_data()
+ ngx.log(ngx.ERR, "body: ", body)
+ ngx.say(body)
+ }
+ }
+ }
+
+ upstream foo {
+ server 127.0.0.1:$TEST_NGINX_RAND_PORT_1 max_fails=0;
+
+ balancer_by_lua_block {
+ local bal = require "ngx.balancer"
+ ngx.req.set_body_data("hello world")
+ assert(bal.recreate_request())
+ }
+ }
+
+--- config
+ location = /t {
+ proxy_http_version 1.1;
+ proxy_set_header Connection "";
+ proxy_pass http://foo;
+ }
+--- request
+GET /t
+--- error_code: 200
+--- response_body
+hello world