diff --git a/minetest.conf.example b/minetest.conf.example
index 7b8ab369..7e5228be 100644
--- a/minetest.conf.example
+++ b/minetest.conf.example
@@ -100,6 +100,9 @@
 #new_style_water = false
 # Max liquids processed per step
 #liquid_loop_max = 10000
+# The time (in seconds) that the liquids queue may grow beyond processing
+# capacity until an attempt is made to decrease its size by dumping old queue items
+#liquid_queue_purge_time = 30
 # Update liquids every .. recommend for finite: 0.2
 #liquid_update = 1.0
 # Enable nice leaves; disable for speed
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp
index 1ebf5dc4..5b83c269 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -277,6 +277,7 @@ void set_default_settings(Settings *settings)
 
 	//liquid stuff
 	settings->setDefault("liquid_loop_max", "10000");
+	settings->setDefault("liquid_queue_purge_time", "30");
 	settings->setDefault("liquid_update", "1.0");
 
 	//mapgen stuff
diff --git a/src/map.cpp b/src/map.cpp
index 009bc3d7..10a6f628 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -76,7 +76,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 Map::Map(std::ostream &dout, IGameDef *gamedef):
 	m_dout(dout),
 	m_gamedef(gamedef),
-	m_sector_cache(NULL)
+	m_sector_cache(NULL),
+	m_transforming_liquid_loop_count_multiplier(1.0f),
+	m_unprocessed_count(0),
+	m_inc_trending_up_start_time(0),
+	m_queue_size_timer_started(false)
 {
 }
 
@@ -1611,6 +1615,7 @@ s32 Map::transforming_liquid_size() {
 
 void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
 {
+
 	INodeDefManager *nodemgr = m_gamedef->ndef();
 
 	DSTACK(__FUNCTION_NAME);
@@ -1619,6 +1624,8 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
 	u32 loopcount = 0;
 	u32 initial_size = m_transforming_liquid.size();
 
+	u32 curr_time = getTime(PRECISION_MILLI);
+
 	/*if(initial_size != 0)
 		infostream<<"transformLiquids(): initial_size="<<initial_size<<std::endl;*/
 
@@ -1628,7 +1635,27 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
 	// List of MapBlocks that will require a lighting update (due to lava)
 	std::map<v3s16, MapBlock*> lighting_modified_blocks;
 
-	u16 loop_max = g_settings->getU16("liquid_loop_max");
+	u32 liquid_loop_max = g_settings->getS32("liquid_loop_max");
+	u32 loop_max = liquid_loop_max;
+
+//	std::cout << "transformLiquids(): loopmax initial="
+//	           << loop_max * m_transforming_liquid_loop_count_multiplier;
+
+	// If liquid_loop_max is not keeping up with the queue size increase
+	// loop_max up to a maximum of liquid_loop_max * dedicated_server_step.
+	if (m_transforming_liquid.size() > loop_max * 2) {
+		// "Burst" mode
+		float server_step = g_settings->getFloat("dedicated_server_step");
+		if (m_transforming_liquid_loop_count_multiplier - 1.0 < server_step)
+			m_transforming_liquid_loop_count_multiplier *= 1.0 + server_step / 10;
+	} else {
+		m_transforming_liquid_loop_count_multiplier = 1.0;
+	}
+
+	loop_max *= m_transforming_liquid_loop_count_multiplier;
+
+//	std::cout << " queue sz=" << m_transforming_liquid.size()
+//	           << " loop_max=" << loop_max;
 
 	while(m_transforming_liquid.size() != 0)
 	{
@@ -1884,6 +1911,54 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
 	while (must_reflow.size() > 0)
 		m_transforming_liquid.push_back(must_reflow.pop_front());
 	updateLighting(lighting_modified_blocks, modified_blocks);
+
+
+	/*
+	 * Queue size limiting
+	 */
+	u32 prev_unprocessed = m_unprocessed_count;
+	m_unprocessed_count = m_transforming_liquid.size();
+
+	// if unprocessed block count is decreasing or stable
+	if (m_unprocessed_count <= prev_unprocessed) {
+		m_queue_size_timer_started = false;
+	} else {
+		if (!m_queue_size_timer_started)
+			m_inc_trending_up_start_time = curr_time;
+		m_queue_size_timer_started = true;
+	}
+
+	u16 time_until_purge = g_settings->getU16("liquid_queue_purge_time");
+	time_until_purge *= 1000;	// seconds -> milliseconds
+
+//	std::cout << " growing for: "
+//	           << (m_queue_size_timer_started ? curr_time - m_inc_trend_up_start_time : 0)
+//	           << "ms" << std::endl;
+
+	// Account for curr_time overflowing
+	if (m_queue_size_timer_started && m_inc_trending_up_start_time > curr_time)
+		m_queue_size_timer_started = false;
+
+	/* If the queue has been growing for more than liquid_queue_purge_time seconds
+	 * and the number of unprocessed blocks is still > liquid_loop_max then we
+	 * cannot keep up; dump the oldest blocks from the queue so that the queue
+	 * has liquid_loop_max items in it
+	 */
+	if (m_queue_size_timer_started
+			&& curr_time - m_inc_trending_up_start_time > time_until_purge
+			&& m_unprocessed_count > liquid_loop_max) {
+
+		size_t dump_qty = m_unprocessed_count - liquid_loop_max;
+
+		infostream << "transformLiquids(): DUMPING " << dump_qty
+		           << " blocks from the queue" << std::endl;
+
+		while (dump_qty--)
+			m_transforming_liquid.pop_front();
+
+		m_queue_size_timer_started = false; // optimistically assume we can keep up now
+		m_unprocessed_count = m_transforming_liquid.size();
+	}
 }
 
 NodeMetadata *Map::getNodeMetadata(v3s16 p)
diff --git a/src/map.h b/src/map.h
index c650e51b..70082d66 100644
--- a/src/map.h
+++ b/src/map.h
@@ -366,6 +366,12 @@ protected:
 
 	// Queued transforming water nodes
 	UniqueQueue<v3s16> m_transforming_liquid;
+
+private:
+	f32 m_transforming_liquid_loop_count_multiplier;
+	u32 m_unprocessed_count;
+	u32 m_inc_trending_up_start_time; // milliseconds
+	bool m_queue_size_timer_started;
 };
 
 /*