diff --git a/bin/varnishd/cache/cache_vcl.c b/bin/varnishd/cache/cache_vcl.c
index 068b482..3151719 100644
--- a/bin/varnishd/cache/cache_vcl.c
+++ b/bin/varnishd/cache/cache_vcl.c
@@ -145,6 +145,64 @@ vcl_find(const char *name)
 }
 
 static int
+VCL_Replace(const char *fn, const char *name, struct cli *cli)
+{
+	struct vcls *vcl;
+	struct VCL_conf const *cnf, *old_cnf;
+	void *newdlh, *olddlh;
+
+	ASSERT_CLI();
+	vcl = vcl_find(name);
+	if (vcl == NULL) {
+		VCLI_Out(cli, "No VCL named '%s'", name);
+		return (1);
+	}
+
+	XXXAN(vcl);
+
+	newdlh = dlopen(fn, RTLD_NOW | RTLD_LOCAL);
+
+	if (newdlh == NULL) {
+		VCLI_Out(cli, "dlopen(%s): %s\n", fn, dlerror());
+		return (1);
+	}
+	cnf = dlsym(newdlh, "VCL_conf");
+	if (cnf == NULL) {
+		VCLI_Out(cli, "Internal error: No VCL_conf symbol\n");
+		(void)dlclose(newdlh);
+		return (1);
+	}
+
+	if (cnf->magic != VCL_CONF_MAGIC) {
+		VCLI_Out(cli, "Wrong VCL_CONF_MAGIC\n");
+		(void)dlclose(newdlh);
+		return (1);
+	}
+
+	if (cnf->init_vcl(cli)) {
+		VCLI_Out(cli, "VCL \"%s\" Failed to initialize", name);
+		(void)dlclose(newdlh);
+		return (1);
+	}
+
+	// Launch fini functions
+	(void)vcl->conf->fini_func(NULL);
+	vcl->conf->fini_vcl(NULL);
+
+	// Now switch dlh
+	olddlh = vcl->dlh;
+	Lck_Lock(&vcl_mtx);
+	vcl->dlh = newdlh;
+	memcpy(vcl->conf, cnf, sizeof *cnf);
+	Lck_Unlock(&vcl_mtx);
+
+	// Close old dlh
+	(void)dlclose(olddlh);
+
+	return (0);
+}
+
+static int
 VCL_Load(const char *fn, const char *name, struct cli *cli)
 {
 	struct vcls *vcl;
@@ -275,6 +333,18 @@ ccf_config_load(struct cli *cli, const char * const *av, void *priv)
 }
 
 static void
+ccf_config_reload(struct cli *cli, const char * const *av, void *priv)
+{
+
+	(void)av;
+	(void)priv;
+	ASSERT_CLI();
+	if (VCL_Replace(av[3], av[2], cli))
+		VCLI_SetResult(cli, CLIS_PARAM);
+	return;
+}
+
+static void
 ccf_config_discard(struct cli *cli, const char * const *av, void *priv)
 {
 	struct vcls *vcl;
@@ -353,6 +423,7 @@ static struct cli_proto vcl_cmds[] = {
 	{ CLI_VCL_LIST,         "i", ccf_config_list },
 	{ CLI_VCL_DISCARD,      "i", ccf_config_discard },
 	{ CLI_VCL_USE,          "i", ccf_config_use },
+	{ CLI_VCL_RELOAD,       "i", ccf_config_reload },
 	{ NULL }
 };
 
diff --git a/bin/varnishd/mgt/mgt_cli.c b/bin/varnishd/mgt/mgt_cli.c
index 1d46d82..50eb2fe 100644
--- a/bin/varnishd/mgt/mgt_cli.c
+++ b/bin/varnishd/mgt/mgt_cli.c
@@ -102,6 +102,7 @@ static struct cli_proto cli_proto[] = {
 	{ CLI_VCL_DISCARD,	"", mcf_config_discard, NULL },
 	{ CLI_VCL_LIST,		"", mcf_config_list, NULL },
 	{ CLI_VCL_SHOW,		"", mcf_config_show, NULL },
+	{ CLI_VCL_RELOAD,	"", mcf_config_reload, NULL },
 	{ CLI_PARAM_SHOW,	"", mcf_param_show, NULL },
 	{ CLI_PARAM_SET,	"", mcf_param_set, NULL },
 	{ CLI_PANIC_SHOW,	"", mcf_panic_show, NULL },
diff --git a/bin/varnishd/mgt/mgt_cli.h b/bin/varnishd/mgt/mgt_cli.h
index 8c49abb..0efe1f7 100644
--- a/bin/varnishd/mgt/mgt_cli.h
+++ b/bin/varnishd/mgt/mgt_cli.h
@@ -45,6 +45,7 @@ cli_func_t mcf_config_use;
 cli_func_t mcf_config_discard;
 cli_func_t mcf_config_list;
 cli_func_t mcf_config_show;
+cli_func_t mcf_config_reload;
 
 /* stevedore.c */
 extern struct cli_proto cli_stv[];
diff --git a/bin/varnishd/mgt/mgt_vcc.c b/bin/varnishd/mgt/mgt_vcc.c
index ec117db..1484f2c 100644
--- a/bin/varnishd/mgt/mgt_vcc.c
+++ b/bin/varnishd/mgt/mgt_vcc.c
@@ -674,3 +674,53 @@ mcf_config_show(struct cli *cli, const char * const *av, void *priv)
 		}
 	}
 }
+
+void
+mcf_config_reload(struct cli *cli, const char * const *av, void *priv)
+{
+	struct vclprog *vp;
+	void *dlh, *sym;
+	const char **src;
+	struct vsb *sb;
+	char *vf, *p = NULL;
+	unsigned status;
+
+	(void)priv;
+	if ((vp = mcf_find_vcl(cli, av[2])) != NULL) {
+		if ((dlh = dlopen(vp->fname, RTLD_NOW | RTLD_LOCAL)) == NULL) {
+			VCLI_Out(cli, "failed to load %s: %s\n",
+			    vp->name, dlerror());
+			VCLI_SetResult(cli, CLIS_CANT);
+		} else if ((sym = dlsym(dlh, "srcbody")) == NULL) {
+			VCLI_Out(cli, "failed to locate source for %s: %s\n",
+			    vp->name, dlerror());
+			VCLI_SetResult(cli, CLIS_CANT);
+			AZ(dlclose(dlh));
+		} else {
+			src = sym;
+			vf = mgt_VccCompile(&sb, src[0], 0);
+			if (VSB_len(sb) > 0)
+				VCLI_Out(cli, "%s\n", VSB_data(sb));
+			VSB_delete(sb);
+			if (vf == NULL) {
+				VCLI_Out(cli, "VCL compilation failed");
+				VCLI_SetResult(cli, CLIS_PARAM);
+				return;
+			}
+			VCLI_Out(cli, "VCL compiled.");
+			if (child_pid >= 0 &&
+			    mgt_cli_askchild(&status, &p, "vcl.reload %s %s\n", av[2], vf)) {
+				VCLI_SetResult(cli, status);
+				VCLI_Out(cli, "%s", p);
+			} else {
+				// Delete old .so
+				printf("unlink %s\n", vp->fname);
+				XXXAZ(unlink(vp->fname));
+				free(vp->fname);
+				vp->fname = vf;
+			}
+			free(p);
+			AZ(dlclose(dlh));
+		}
+	}
+}
diff --git a/include/vcli.h b/include/vcli.h
index 04ac11c..1f90a5e 100644
--- a/include/vcli.h
+++ b/include/vcli.h
@@ -108,6 +108,12 @@
 	"\tDisplay the source code for the specified configuration.",	\
 	1, 1
 
+#define CLI_VCL_RELOAD							\
+	"vcl.reload",							\
+	"vcl.reload <configname>",					\
+	"\tReload the VCLi."					,	\
+	1, 2
+
 #define CLI_VCL_USE							\
 	"vcl.use",							\
 	"vcl.use <configname>",						\
