diff --git a/include/grenade/vx/execution_instance_builder.h b/include/grenade/vx/execution_instance_builder.h
index afa6c3b9c8ddc1f4a09416af4e347bc8d86ddda7..8119ff880d9270d0b9a19802527b406d92048a08 100644
--- a/include/grenade/vx/execution_instance_builder.h
+++ b/include/grenade/vx/execution_instance_builder.h
@@ -46,7 +46,7 @@ public:
 	    coordinate::ExecutionInstance const& execution_instance,
 	    IODataMap const& input_list,
 	    IODataMap const& data_output,
-	    lola::vx::v2::Chip const& chip_config,
+	    std::optional<lola::vx::v2::PPUElfFile::symbols_type> const& ppu_symbols,
 	    ExecutionInstancePlaybackHooks& playback_hooks) SYMBOL_VISIBLE;
 
 	/**
@@ -56,7 +56,6 @@ public:
 
 	struct PlaybackPrograms
 	{
-		stadls::vx::v2::PlaybackProgram static_config;
 		std::vector<stadls::vx::v2::PlaybackProgram> realtime;
 		bool has_hook_around_realtime;
 	};
@@ -89,7 +88,7 @@ private:
 
 	ConstantReferenceIODataMap m_local_external_data;
 
-	lola::vx::v2::Chip m_initial_config;
+	std::optional<lola::vx::v2::PPUElfFile::symbols_type> m_ppu_symbols;
 
 	ExecutionInstancePlaybackHooks& m_playback_hooks;
 
diff --git a/src/grenade/vx/execution_instance_builder.cpp b/src/grenade/vx/execution_instance_builder.cpp
index 242b3c2f9614c98512e68bc4bce7dd68b1a343c3..63a613a8a8406a801d991f2b0410f4c9704ff030 100644
--- a/src/grenade/vx/execution_instance_builder.cpp
+++ b/src/grenade/vx/execution_instance_builder.cpp
@@ -46,14 +46,14 @@ ExecutionInstanceBuilder::ExecutionInstanceBuilder(
     coordinate::ExecutionInstance const& execution_instance,
     IODataMap const& input_list,
     IODataMap const& data_output,
-    lola::vx::v2::Chip const& chip_config,
+    std::optional<lola::vx::v2::PPUElfFile::symbols_type> const& ppu_symbols,
     ExecutionInstancePlaybackHooks& playback_hooks) :
     m_graph(graph),
     m_execution_instance(execution_instance),
     m_input_list(input_list),
     m_data_output(data_output),
     m_local_external_data(),
-    m_initial_config(chip_config),
+    m_ppu_symbols(ppu_symbols),
     m_playback_hooks(playback_hooks),
     m_post_vertices(),
     m_local_data(),
@@ -827,37 +827,16 @@ ExecutionInstanceBuilder::PlaybackPrograms ExecutionInstanceBuilder::generate()
 		builder.merge_back(m_playback_hooks.pre_realtime);
 		builder.merge_back(m_playback_hooks.post_realtime);
 		m_chunked_program = {builder.done()};
-		return {{}, m_chunked_program, false};
+		return {m_chunked_program, false};
 	}
 
 	// playback builder sequence to be concatenated in the end
 	std::vector<PlaybackProgramBuilder> builders;
 
-	// add pre static config playback hook
-	auto config_builder = std::move(m_playback_hooks.pre_static_config);
-
-	// generate static configuration
-	auto [static_config, ppu_symbols] =
-	    ExecutionInstanceConfigVisitor(m_graph, m_execution_instance, m_initial_config)();
-	config_builder.write(ChipOnDLS(), static_config);
-	// wait for CapMem to settle
-	config_builder.block_until(BarrierOnFPGA(), Barrier::omnibus);
-	config_builder.write(TimerOnDLS(), Timer());
-	config_builder.block_until(
-	    TimerOnDLS(), Timer::Value(100000 * Timer::Value::fpga_clock_cycles_per_us));
-
-	// bring PPUs in running state
-	bool const enable_ppu = static_cast<bool>(ppu_symbols);
-	if (enable_ppu) {
-		for (auto const ppu : iter_all<PPUOnDLS>()) {
-			PPUControlRegister ctrl;
-			ctrl.set_inhibit_reset(true);
-			config_builder.write(ppu.toPPUControlRegisterOnDLS(), ctrl);
-		}
-	}
 	// generate playback snippet for neuron resets
 	auto [builder_neuron_reset, _] = stadls::vx::generate(m_neuron_resets);
 
+	auto const enable_ppu = static_cast<bool>(m_ppu_symbols);
 	bool const has_cadc_readout = std::any_of(
 	    m_ticket_requests.begin(), m_ticket_requests.end(), [](auto const v) { return v; });
 	assert(has_cadc_readout ? enable_ppu : true);
@@ -884,14 +863,14 @@ ExecutionInstanceBuilder::PlaybackPrograms ExecutionInstanceBuilder::generate()
 	std::optional<PPUMemoryBlockOnPPU> ppu_scheduler_event_drop_count_coord;
 	std::vector<PPUMemoryBlockOnPPU> ppu_timer_event_drop_count_coord;
 	if (enable_ppu) {
-		assert(ppu_symbols);
-		ppu_status_coord = ppu_symbols->at("status").coordinate.toMin();
-		ppu_result_coord = ppu_symbols->at("cadc_result").coordinate;
-		ppu_runtime_coord = ppu_symbols->at("runtime").coordinate.toMin();
-		if (ppu_symbols->contains("scheduler_event_drop_count")) {
+		assert(m_ppu_symbols);
+		ppu_status_coord = m_ppu_symbols->at("status").coordinate.toMin();
+		ppu_result_coord = m_ppu_symbols->at("cadc_result").coordinate;
+		ppu_runtime_coord = m_ppu_symbols->at("runtime").coordinate.toMin();
+		if (m_ppu_symbols->contains("scheduler_event_drop_count")) {
 			ppu_scheduler_event_drop_count_coord.emplace(
-			    ppu_symbols->at("scheduler_event_drop_count").coordinate);
-			for (auto const& [name, symbol] : *ppu_symbols) {
+			    m_ppu_symbols->at("scheduler_event_drop_count").coordinate);
+			for (auto const& [name, symbol] : *m_ppu_symbols) {
 				if (name.starts_with("timer") && name.ends_with("event_drop_count")) {
 					ppu_timer_event_drop_count_coord.push_back(symbol.coordinate);
 				}
@@ -931,19 +910,6 @@ ExecutionInstanceBuilder::PlaybackPrograms ExecutionInstanceBuilder::generate()
 			wait_for_ppu_command_idle.block_until(
 			    PollingOmnibusBlockOnFPGA(), PollingOmnibusBlock());
 		}
-		// wait for PPUs to be ready
-		for (auto const ppu : iter_all<PPUOnDLS>()) {
-			PollingOmnibusBlockConfig config;
-			config.set_address(PPUMemoryWord::addresses<PollingOmnibusBlockConfig::Address>(
-			                       PPUMemoryWordOnDLS(ppu_status_coord, ppu))
-			                       .at(0));
-			config.set_target(
-			    PollingOmnibusBlockConfig::Value(static_cast<uint32_t>(ppu::Status::idle)));
-			config.set_mask(PollingOmnibusBlockConfig::Value(0xffffffff));
-			config_builder.write(PollingOmnibusBlockConfigOnFPGA(), config);
-			config_builder.block_until(BarrierOnFPGA(), Barrier::omnibus);
-			config_builder.block_until(PollingOmnibusBlockOnFPGA(), PollingOmnibusBlock());
-		}
 	}
 
 	// get whether any of {pre,post}_realtime hooks are present
@@ -1192,7 +1158,7 @@ ExecutionInstanceBuilder::PlaybackPrograms ExecutionInstanceBuilder::generate()
 	if (!builder.empty()) {
 		m_chunked_program.push_back(builder.done());
 	}
-	return {config_builder.done(), m_chunked_program, has_hook_around_realtime};
+	return {m_chunked_program, has_hook_around_realtime};
 }
 
 } // namespace grenade::vx
diff --git a/src/grenade/vx/execution_instance_node.cpp b/src/grenade/vx/execution_instance_node.cpp
index b20ca78bc8061d789cb4963ca71cf776c29e7417..43f969d181bade3960893c6c4b086ec67c59d340 100644
--- a/src/grenade/vx/execution_instance_node.cpp
+++ b/src/grenade/vx/execution_instance_node.cpp
@@ -2,6 +2,10 @@
 
 #include "grenade/vx/backend/connection.h"
 #include "grenade/vx/backend/run.h"
+#include "grenade/vx/execution_instance_config_visitor.h"
+#include "grenade/vx/ppu/status.h"
+#include "haldls/vx/v2/barrier.h"
+#include "haldls/vx/v2/timer.h"
 #include "hate/timer.h"
 #include <log4cxx/logger.h>
 
@@ -33,8 +37,16 @@ void ExecutionInstanceNode::operator()(tbb::flow::continue_msg)
 	using namespace halco::common;
 	using namespace halco::hicann_dls::vx::v2;
 
+	hate::Timer const initial_config_timer;
+	lola::vx::v2::Chip initial_config = chip_config;
+	auto const ppu_symbols =
+	    std::get<1>(ExecutionInstanceConfigVisitor(graph, execution_instance, initial_config)());
+	LOG4CXX_TRACE(
+	    logger,
+	    "operator(): Constructed initial configuration in " << initial_config_timer.print() << ".");
+
 	ExecutionInstanceBuilder builder(
-	    graph, execution_instance, input_data_map, data_map, chip_config, playback_hooks);
+	    graph, execution_instance, input_data_map, data_map, ppu_symbols, playback_hooks);
 
 	hate::Timer const preprocess_timer;
 	builder.pre_process();
@@ -43,6 +55,46 @@ void ExecutionInstanceNode::operator()(tbb::flow::continue_msg)
 
 	// build PlaybackProgram
 	hate::Timer const build_timer;
+
+	// add pre static config playback hook
+	auto config_builder = std::move(playback_hooks.pre_static_config);
+
+	// generate static configuration
+	config_builder.write(ChipOnDLS(), initial_config);
+
+	// wait for CapMem to settle
+	config_builder.block_until(BarrierOnFPGA(), haldls::vx::v2::Barrier::omnibus);
+	config_builder.write(TimerOnDLS(), haldls::vx::v2::Timer());
+	config_builder.block_until(
+	    TimerOnDLS(), haldls::vx::v2::Timer::Value(
+	                      100000 * haldls::vx::v2::Timer::Value::fpga_clock_cycles_per_us));
+
+	// bring PPUs in running state
+	if (ppu_symbols) {
+		for (auto const ppu : iter_all<PPUOnDLS>()) {
+			haldls::vx::v2::PPUControlRegister ctrl;
+			ctrl.set_inhibit_reset(true);
+			config_builder.write(ppu.toPPUControlRegisterOnDLS(), ctrl);
+		}
+		auto const ppu_status_coord = ppu_symbols->at("status").coordinate.toMin();
+		// wait for PPUs to be ready
+		for (auto const ppu : iter_all<PPUOnDLS>()) {
+			using namespace haldls::vx::v2;
+			PollingOmnibusBlockConfig config;
+			config.set_address(PPUMemoryWord::addresses<PollingOmnibusBlockConfig::Address>(
+			                       PPUMemoryWordOnDLS(ppu_status_coord, ppu))
+			                       .at(0));
+			config.set_target(
+			    PollingOmnibusBlockConfig::Value(static_cast<uint32_t>(ppu::Status::idle)));
+			config.set_mask(PollingOmnibusBlockConfig::Value(0xffffffff));
+			config_builder.write(PollingOmnibusBlockConfigOnFPGA(), config);
+			config_builder.block_until(BarrierOnFPGA(), Barrier::omnibus);
+			config_builder.block_until(PollingOmnibusBlockOnFPGA(), PollingOmnibusBlock());
+		}
+	}
+	auto initial_config_program = config_builder.done();
+
+	// build realtime programs
 	auto program = builder.generate();
 	LOG4CXX_TRACE(logger, "operator(): Built PlaybackPrograms in " << build_timer.print() << ".");
 
@@ -56,10 +108,10 @@ void ExecutionInstanceNode::operator()(tbb::flow::continue_msg)
 
 	// execute
 	hate::Timer const exec_timer;
-	if (!program.realtime.empty() || !program.static_config.empty()) {
+	if (!program.realtime.empty() || !initial_config_program.empty()) {
 		std::lock_guard lock(continuous_chunked_program_execution_mutex);
-		auto static_config_reinit = connection.create_reinit_stack_entry();
-		static_config_reinit.set(program.static_config, true);
+		auto initial_config_reinit = connection.create_reinit_stack_entry();
+		initial_config_reinit.set(initial_config_program, true);
 		for (auto& p : program.realtime) {
 			backend::run(connection, p);
 		}