diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua
index d5161066771cc93a21cc7819f64e2120ae65e81c..8b5e7c4bf1afd30899401fca6679201ffe492328 100644
--- a/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua
+++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua
@@ -296,4 +296,14 @@ function M.subprocess.popen(path, argt, options)
 
 	return pid, parentfds
 end
+
+function M.get_mem_total()
+	for line in io.lines('/proc/meminfo') do
+		local match = line:match('^MemTotal:%s+(%d+)')
+		if match then
+			return tonumber(match)
+		end
+	end
+end
+
 return M
diff --git a/package/gluon-mesh-vpn-fastd/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/fastd.lua b/package/gluon-mesh-vpn-fastd/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/fastd.lua
index 20ac4777c53cabcdd7c9725173283b6d6f79c735..c6be84c4d6c7ec35f9b5f7b1cdc941cc049544a3 100644
--- a/package/gluon-mesh-vpn-fastd/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/fastd.lua
+++ b/package/gluon-mesh-vpn-fastd/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/fastd.lua
@@ -4,6 +4,8 @@ local site = require 'gluon.site'
 local util = require 'gluon.util'
 local vpn_core = require 'gluon.mesh-vpn'
 
+local unistd = require 'posix.unistd'
+
 local M = {}
 
 function M.public_key()
@@ -25,18 +27,46 @@ function M.active()
 	return site.mesh_vpn.fastd() ~= nil
 end
 
+local function set_limit_simple_tc(ingress_limit, egress_limit)
+	uci:section('simple-tc', 'interface', 'mesh_vpn', {
+		ifname = vpn_core.get_interface(),
+		enabled = true,
+		limit_egress = egress_limit,
+		limit_ingress = ingress_limit,
+	})
+end
+
+local function set_limit_sqm(ingress_limit, egress_limit)
+	uci:section('sqm', 'queue', 'mesh_vpn', {
+		interface = vpn_core.get_interface(),
+		enabled = true,
+		upload = egress_limit,
+		download = ingress_limit,
+		qdisc = 'cake',
+		script = 'piece_of_cake.qos',
+		debug_logging = '0',
+		verbosity = '5',
+	})
+end
+
+local function sqm_available()
+	return unistd.access('/lib/gluon/mesh-vpn/sqm')
+end
+
 function M.set_limit(ingress_limit, egress_limit)
 	uci:delete('simple-tc', 'mesh_vpn')
+	uci:delete('sqm', 'mesh_vpn')
+
 	if ingress_limit ~= nil and egress_limit ~= nil then
-		uci:section('simple-tc', 'interface', 'mesh_vpn', {
-			ifname = vpn_core.get_interface(),
-			enabled = true,
-			limit_egress = egress_limit,
-			limit_ingress = ingress_limit,
-		})
+		if sqm_available() and util.get_mem_total() > 200*1024 then
+			set_limit_sqm(ingress_limit, egress_limit)
+		else
+			set_limit_simple_tc(ingress_limit, egress_limit)
+		end
 	end
 
 	uci:save('simple-tc')
+	uci:save('sqm')
 end
 
 function M.mtu()
diff --git a/package/gluon-mesh-vpn-sqm/Makefile b/package/gluon-mesh-vpn-sqm/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..7c55693167c59ec7258a2619c9dfca9e09219a81
--- /dev/null
+++ b/package/gluon-mesh-vpn-sqm/Makefile
@@ -0,0 +1,18 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gluon-mesh-vpn-sqm
+
+include ../gluon.mk
+
+define Package/gluon-mesh-vpn-sqm
+  TITLE:=Adds support for SQM with CAKE on VPN links
+  DEPENDS:= +gluon-mesh-vpn-core +sqm-scripts
+endef
+
+define Package/gluon-mesh-vpn-sqm/install
+	$(Gluon/Build/Install)
+	$(INSTALL_DIR) $(1)/lib/gluon/mesh-vpn
+	touch $(1)/lib/gluon/mesh-vpn/sqm
+endef
+
+$(eval $(call BuildPackageGluon,gluon-mesh-vpn-sqm))
diff --git a/package/gluon-status-page/luasrc/lib/gluon/upgrade/500-status-page b/package/gluon-status-page/luasrc/lib/gluon/upgrade/500-status-page
index 9e54307e832b25043012af44f40d47e6edc0b01f..0186d067a61fbe8b0c8c91cfa53cff402b350f13 100755
--- a/package/gluon-status-page/luasrc/lib/gluon/upgrade/500-status-page
+++ b/package/gluon-status-page/luasrc/lib/gluon/upgrade/500-status-page
@@ -1,19 +1,11 @@
 #!/usr/bin/lua
 
 local uci = require('simple-uci').cursor()
+local util = require 'gluon.util'
 
 
-local function get_mem_total()
-	for line in io.lines('/proc/meminfo') do
-		local match = line:match('^MemTotal:%s+(%d+)')
-		if match then
-			return tonumber(match)
-		end
-	end
-end
-
 local max_requests = 32
-if get_mem_total() < 48*1024 then
+if util.get_mem_total() < 48*1024 then
 	max_requests = 16
 end