diff --git a/akka-bbb-apps/src/main/resources/application.conf b/akka-bbb-apps/src/main/resources/application.conf
index 7f042e21e13c44fb5d89393a6e180e7ec81e771c..106bea5455ade62086e68a366057b30bd381ab21 100755
--- a/akka-bbb-apps/src/main/resources/application.conf
+++ b/akka-bbb-apps/src/main/resources/application.conf
@@ -47,6 +47,12 @@ inactivity {
     timeLeft=300
 }
 
+expire {
+  # time in seconds
+  lastUserLeft = 60
+  neverJoined = 300
+}
+
 services {
   bbbWebAPI = "http://192.168.23.33/bigbluebutton/api"
   sharedSecret = "changeme"
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
index 4ceeaadec064bdd9ae98088f886504e97fa9a688..ea2b8ef50179981dd9b6b463a69cb4c1f6dd8e2c 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
@@ -24,4 +24,7 @@ trait SystemConfiguration {
 
   lazy val inactivityDeadline = Try(config.getInt("inactivity.deadline")).getOrElse(2 * 3600) // 2 hours
   lazy val inactivityTimeLeft = Try(config.getInt("inactivity.timeLeft")).getOrElse(5 * 60) // 5 minutes
+
+  lazy val expireLastUserLeft = Try(config.getInt("expire.lastUserLeft")).getOrElse(60) // 1 minute
+  lazy val expireNeverJoined = Try(config.getInt("expire.neverJoined")).getOrElse(5 * 60) // 5 minutes
 }
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala
index 2bc622cd7b0e9449c48cb54a4b9e0c37df5caa98..e8c5dfdc3cb4e6f5fbb01120123a987361bd7126 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala
@@ -40,6 +40,7 @@ case class DestroyMeeting(meetingID: String) extends InMessage
 case class StartMeeting(meetingID: String) extends InMessage
 case class EndMeeting(meetingId: String) extends InMessage
 case class LockSetting(meetingID: String, locked: Boolean, settings: Map[String, Boolean]) extends InMessage
+case class UpdateMeetingExpireMonitor(meetingID: String, hasUser: Boolean) extends InMessage
 
 ////////////////////////////////////////////////////////////////////////////////////// 
 // Breakout room
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
index ab4eda3a13d537f7abcab6d38779609b319a42e0..1a6197fc55c4656f3e39b430ab576d908b65db29 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
@@ -53,7 +53,7 @@ class MeetingActor(val mProps: MeetingProperties,
 
   def receive = {
     case msg: ActivityResponse => handleActivityResponse(msg)
-    case msg: MonitorNumberOfUsers => handleMonitorNumberOfWebUsers(msg)
+    case msg: MonitorNumberOfUsers => handleMonitorNumberOfUsers(msg)
     case msg: ValidateAuthToken => handleValidateAuthToken(msg)
     case msg: RegisterUser => handleRegisterUser(msg)
     case msg: UserJoinedVoiceConfMessage => handleUserJoinedVoiceConfMessage(msg)
@@ -302,7 +302,12 @@ class MeetingActor(val mProps: MeetingProperties,
     }
   }
 
-  def handleMonitorNumberOfWebUsers(msg: MonitorNumberOfUsers) {
+  def handleMonitorNumberOfUsers(msg: MonitorNumberOfUsers) {
+    monitorNumberOfWebUsers()
+    monitorNumberOfUsers()
+  }
+
+  def monitorNumberOfWebUsers() {
     if (Users.numWebUsers(liveMeeting.users) == 0 && liveMeeting.meetingModel.lastWebUserLeftOn > 0) {
       if (liveMeeting.timeNowInMinutes - liveMeeting.meetingModel.lastWebUserLeftOn > 2) {
         log.info("Empty meeting. Ejecting all users from voice. meetingId={}", mProps.meetingID)
@@ -311,6 +316,12 @@ class MeetingActor(val mProps: MeetingProperties,
     }
   }
 
+  def monitorNumberOfUsers() {
+    val hasUsers = Users.numUsers(liveMeeting.users) != 0
+    // TODO: We could use a better control over this message to send it just when it really matters :)
+    eventBus.publish(BigBlueButtonEvent(mProps.meetingID, UpdateMeetingExpireMonitor(mProps.meetingID, hasUsers)))
+  }
+
   def handleSendTimeRemainingUpdate(msg: SendTimeRemainingUpdate) {
     if (mProps.duration > 0) {
       val endMeetingTime = liveMeeting.meetingModel.startedOn + (mProps.duration * 60)
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActorInternal.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActorInternal.scala
index 70e9927cc2a6c706f4ec2a25caae4edfbdae2a69..a698eba3e0f93794c41a4b9fbee8106b0ca4d014 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActorInternal.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActorInternal.scala
@@ -55,11 +55,32 @@ class MeetingActorInternal(val mProps: MeetingProperties,
     time
   }
 
+  private def getExpireNeverJoined(): Int = {
+    val time = expireNeverJoined
+    log.debug("ExpireNeverJoined: {} seconds", time)
+    time
+  }
+
+  private def getExpireLastUserLeft(): Int = {
+    val time = expireLastUserLeft
+    log.debug("ExpireLastUserLeft: {} seconds", time)
+    time
+  }
+
+  private val MonitorFrequency = 10 seconds
+
   private val InactivityDeadline = FiniteDuration(getInactivityDeadline(), "seconds")
   private val InactivityTimeLeft = FiniteDuration(getInactivityTimeLeft(), "seconds")
-  private val MonitorFrequency = 10 seconds
-  private var deadline = InactivityDeadline.fromNow
+  private var inactivity = InactivityDeadline.fromNow
   private var inactivityWarning: Deadline = null
+
+  private val ExpireMeetingDuration = FiniteDuration(mProps.duration, "minutes")
+  private val ExpireMeetingNeverJoined = FiniteDuration(getExpireNeverJoined(), "seconds")
+  private val ExpireMeetingLastUserLeft = FiniteDuration(getExpireLastUserLeft(), "seconds")
+  private var meetingExpire = ExpireMeetingNeverJoined.fromNow
+  // Zero minutes means the meeting has no duration control
+  private var meetingDuration: Deadline = if (ExpireMeetingDuration > (0 minutes)) ExpireMeetingDuration.fromNow else null
+
   context.system.scheduler.schedule(5 seconds, MonitorFrequency, self, "Monitor")
 
   // Query to get voice conference users
@@ -74,12 +95,14 @@ class MeetingActorInternal(val mProps: MeetingProperties,
 
   def receive = {
     case "Monitor" => handleMonitor()
+    case msg: UpdateMeetingExpireMonitor => handleUpdateMeetingExpireMonitor(msg)
     case msg: Object => handleMessage(msg)
   }
 
   def handleMonitor() {
     handleMonitorActivity()
     handleMonitorNumberOfWebUsers()
+    handleMonitorExpiration()
   }
 
   def handleMessage(msg: Object) {
@@ -102,12 +125,12 @@ class MeetingActorInternal(val mProps: MeetingProperties,
   }
 
   private def handleMonitorActivity() {
-    if (deadline.isOverdue() && inactivityWarning != null && inactivityWarning.isOverdue()) {
+    if (inactivity.isOverdue() && inactivityWarning != null && inactivityWarning.isOverdue()) {
       log.info("Closing meeting {} due to inactivity for {} seconds", mProps.meetingID, InactivityDeadline.toSeconds)
       updateInactivityMonitors()
       eventBus.publish(BigBlueButtonEvent(mProps.meetingID, EndMeeting(mProps.meetingID)))
       // Or else make sure to send only one warning message
-    } else if (deadline.isOverdue() && inactivityWarning == null) {
+    } else if (inactivity.isOverdue() && inactivityWarning == null) {
       log.info("Sending inactivity warning to meeting {}", mProps.meetingID)
       outGW.send(new InactivityWarning(mProps.meetingID, InactivityTimeLeft.toSeconds))
       // We add 5 seconds so clients will have enough time to process the message
@@ -115,8 +138,38 @@ class MeetingActorInternal(val mProps: MeetingProperties,
     }
   }
 
+  private def handleMonitorExpiration() {
+    if (meetingExpire != null && meetingExpire.isOverdue()) {
+      // User related meeting expiration methods
+      log.debug("Meeting {} expired. No users", mProps.meetingID)
+      meetingExpire = null
+      eventBus.publish(BigBlueButtonEvent(mProps.meetingID, EndMeeting(mProps.meetingID)))
+    } else if (meetingDuration != null && meetingDuration.isOverdue()) {
+      // Default meeting duration
+      meetingDuration = null
+      log.debug("Meeting {} expired. Reached it's fixed duration of {}", mProps.meetingID, ExpireMeetingDuration.toString())
+      eventBus.publish(BigBlueButtonEvent(mProps.meetingID, EndMeeting(mProps.meetingID)))
+    }
+  }
+
+  private def handleUpdateMeetingExpireMonitor(msg: UpdateMeetingExpireMonitor) {
+    if (msg.hasUser) {
+      if (meetingExpire != null) {
+        // User joined. Forget about this expiration for now
+        log.debug("Meeting has users. Stopping expiration for meeting {}", mProps.meetingID)
+        meetingExpire = null
+      }
+    } else {
+      if (meetingExpire == null) {
+        // User list is empty. Start this meeting expiration method
+        log.debug("Meeting has no users. Starting {} expiration for meeting {}", ExpireMeetingLastUserLeft.toString(), mProps.meetingID)
+        meetingExpire = ExpireMeetingLastUserLeft.fromNow
+      }
+    }
+  }
+
   private def updateInactivityMonitors() {
-    deadline = InactivityDeadline.fromNow
+    inactivity = InactivityDeadline.fromNow
     inactivityWarning = null
   }
 
diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/domain/Meeting.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/domain/Meeting.java
index 40a0a14e49b49155aa843405a37d34a41dfbace0..d33e3907f516ce790818905c5062f7add308a0dc 100755
--- a/bbb-common-web/src/main/java/org/bigbluebutton/api/domain/Meeting.java
+++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/domain/Meeting.java
@@ -27,8 +27,6 @@ import org.apache.commons.lang3.RandomStringUtils;
 
 public class Meeting {
 
-	private static final long MILLIS_IN_A_MINUTE = 60000;
-	
 	private String name;
 	private String extMeetingId;
 	private String intMeetingId;
@@ -65,8 +63,6 @@ public class Meeting {
 	private final Boolean isBreakout;
 	private final List<String> breakoutRooms = new ArrayList();
 	
-	private long lastUserLeftOn = 0;
-	
     public Meeting(Builder builder) {
         name = builder.name;
         extMeetingId = builder.externalId;
@@ -293,7 +289,6 @@ public class Meeting {
 
 	public User userLeft(String userid){
 		User u = (User) users.remove(userid);	
-		if (users.isEmpty()) lastUserLeftOn = System.currentTimeMillis();
 		return u;
 	}
 
@@ -317,54 +312,6 @@ public class Meeting {
 	public String getDialNumber() {
 		return dialNumber;
 	}
-	
-	public boolean wasNeverJoined(int expiry) {
-		return (hasStarted() && !hasEnded() && nobodyJoined(expiry));
-	}
-	
-	private boolean meetingInfinite() {
-		/* Meeting stays runs infinitely */
-	  return 	duration == 0;
-	}
-	
-	private boolean nobodyJoined(int expiry) {
-		if (expiry == 0) return false; /* Meeting stays created infinitely */
-		
-		long now = System.currentTimeMillis();
-
-		return (!userHasJoined && (now - createdTime) >  (expiry * MILLIS_IN_A_MINUTE));
-	}
-
-	private boolean hasBeenEmptyFor(int expiry) {
-		long now = System.currentTimeMillis();
-		return (now - lastUserLeftOn > (expiry * MILLIS_IN_A_MINUTE));
-	}
-	
-	private boolean isEmpty() {
-		return users.isEmpty();
-	}
-	
-	public boolean hasExpired(int expiry) {
-		return (hasStarted() && userHasJoined && isEmpty() && hasBeenEmptyFor(expiry));
-	}
-	
-	public boolean hasExceededDuration() {
-		return (hasStarted() && !hasEnded() && pastDuration());
-	}
-
-	private boolean pastDuration() {
-		if (meetingInfinite()) return false; 
-		long now = System.currentTimeMillis();
-		return (now - startTime > (duration * MILLIS_IN_A_MINUTE));
-	}
-	
-	private boolean hasStarted() {
-		return startTime > 0;
-	}
-	
-	private boolean hasEnded() {
-		return endTime > 0;
-	}
 
 	public int getNumListenOnly() {
 		int sum = 0;
diff --git a/bigbluebutton-config/bin/bbb-conf b/bigbluebutton-config/bin/bbb-conf
index 1ef1013687e1add01f309744b9dbfeed381d30ac..76dd01e5a13d1b02e591d0b171f8d6cc22982075 100755
--- a/bigbluebutton-config/bin/bbb-conf
+++ b/bigbluebutton-config/bin/bbb-conf
@@ -1341,21 +1341,6 @@ check_state() {
 		fi
 	fi
 
-        if grep -q removeMeetingWhenEnded=false $SERVLET_DIR/bigbluebutton/WEB-INF/classes/bigbluebutton.properties; then
-                echo "# Warning: In"
-                echo "#"
-                echo "#    $SERVLET_DIR/bigbluebutton/WEB-INF/classes/bigbluebutton.properties"
-                echo "#"
-                echo "# detected the setting"
-                echo "#"
-                echo "#    removeMeetingWhenEnded=false"
-                echo "#"
-                echo "# You should set this value to true.  It enables bbb-web to immediately purge a meeting from"
-		echo "# memory when receiving an end API call.  Otherwise, users must wait about 2 minutes"
-		echo "# request before creating a meeting with the same meetingID but with different parameters."
-                echo
-        fi
-
         if (( $MEM < 3940 )); then
 		echo "# Warning: You are running BigBlueButton on a server with less than 4G of memory.  Your"
 		echo "# performance may suffer."
diff --git a/bigbluebutton-web/grails-app/conf/bigbluebutton.properties b/bigbluebutton-web/grails-app/conf/bigbluebutton.properties
index f7b8dec5a4fddc37949b5d8bd6cc200a9889ae7e..078f95b46d1dd54a1037cb36d633d5b6d902fe00 100755
--- a/bigbluebutton-web/grails-app/conf/bigbluebutton.properties
+++ b/bigbluebutton-web/grails-app/conf/bigbluebutton.properties
@@ -115,19 +115,6 @@ defaultMaxUsers=0
 # Current default is 0 (meeting doesn't end).
 defaultMeetingDuration=0
 
-# Remove the meeting from memory when the end API is called.
-# This allows 3rd-party apps to recycle the meeting right-away
-# instead of waiting for the meeting to expire (see below).
-removeMeetingWhenEnded=true
-
-# The number of minutes before the system removes the meeting from memory.
-defaultMeetingExpireDuration=1
-
-# The number of minutes the system waits when a meeting is created and when
-# a user joins. If after this period, a user hasn't joined, the meeting is
-# removed from memory.
-defaultMeetingCreateJoinDuration=5
-
 # Disable recording by default. 
 #   true - don't record even if record param in the api call is set to record
 #   false - when record param is passed from api, override this default
diff --git a/bigbluebutton-web/grails-app/conf/spring/resources.xml b/bigbluebutton-web/grails-app/conf/spring/resources.xml
index 20edb6e04edbe2b035e62a5230cb3f66a99e5e83..0ad5762aa0653dfc3f93ea371db91ead12e248ff 100755
--- a/bigbluebutton-web/grails-app/conf/spring/resources.xml
+++ b/bigbluebutton-web/grails-app/conf/spring/resources.xml
@@ -31,8 +31,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
         <property name="redisStorageService" ref="redisStorageService"/>
     </bean>
 
-    <bean id="expiredMeetingCleanupTimerTask" class="org.bigbluebutton.web.services.ExpiredMeetingCleanupTimerTask"/>
-
   <bean id="registeredUserCleanupTimerTask" class="org.bigbluebutton.web.services.RegisteredUserCleanupTimerTask"/>
 
   <bean id="keepAliveService" class="org.bigbluebutton.web.services.KeepAliveService" 
@@ -42,10 +40,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
   </bean>
 
     <bean id="meetingService" class="org.bigbluebutton.api.MeetingService" init-method="start" destroy-method="stop">
-        <property name="defaultMeetingExpireDuration" value="${defaultMeetingExpireDuration}"/>
-        <property name="defaultMeetingCreateJoinDuration" value="${defaultMeetingCreateJoinDuration}"/>
-        <property name="removeMeetingWhenEnded" value="${removeMeetingWhenEnded}"/>
-        <property name="expiredMeetingCleanupTimerTask" ref="expiredMeetingCleanupTimerTask"/>
         <property name="messagingService" ref="messagingService"/>
         <property name="recordingService" ref="recordingService"/>
         <property name="presDownloadService" ref="presDownloadService"/>
diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/api/MeetingService.java b/bigbluebutton-web/src/java/org/bigbluebutton/api/MeetingService.java
index 7d94c471937a72bb1dfa0a2920b4793848756a92..8030753a95bd53af421089f62c518f1aa8df6d4c 100755
--- a/bigbluebutton-web/src/java/org/bigbluebutton/api/MeetingService.java
+++ b/bigbluebutton-web/src/java/org/bigbluebutton/api/MeetingService.java
@@ -51,7 +51,6 @@ import org.bigbluebutton.api.messaging.messages.MeetingDestroyed;
 import org.bigbluebutton.api.messaging.messages.MeetingEnded;
 import org.bigbluebutton.api.messaging.messages.MeetingStarted;
 import org.bigbluebutton.api.messaging.messages.RegisterUser;
-import org.bigbluebutton.api.messaging.messages.RemoveExpiredMeetings;
 import org.bigbluebutton.api.messaging.messages.UserJoined;
 import org.bigbluebutton.api.messaging.messages.UserJoinedVoice;
 import org.bigbluebutton.api.messaging.messages.UserLeft;
@@ -63,7 +62,6 @@ import org.bigbluebutton.api.messaging.messages.UserStatusChanged;
 import org.bigbluebutton.api.messaging.messages.UserUnsharedWebcam;
 import org.bigbluebutton.presentation.PresentationUrlDownloadService;
 import org.bigbluebutton.api.messaging.messages.StunTurnInfoRequested;
-import org.bigbluebutton.web.services.ExpiredMeetingCleanupTimerTask;
 import org.bigbluebutton.web.services.RegisteredUserCleanupTimerTask;
 import org.bigbluebutton.web.services.turn.StunServer;
 import org.bigbluebutton.web.services.turn.StunTurnService;
@@ -90,14 +88,10 @@ public class MeetingService implements MessageListener {
     private final ConcurrentMap<String, Meeting> meetings;
     private final ConcurrentMap<String, UserSession> sessions;
 
-    private int defaultMeetingExpireDuration = 1;
-    private int defaultMeetingCreateJoinDuration = 5;
     private RecordingService recordingService;
     private MessagingService messagingService;
-    private ExpiredMeetingCleanupTimerTask cleaner;
     private RegisteredUserCleanupTimerTask registeredUserCleaner;
     private StunTurnService stunTurnService;
-    private boolean removeMeetingWhenEnded = false;
 
     private ParamsProcessorUtil paramsProcessorUtil;
     private PresentationUrlDownloadService presDownloadService;
@@ -131,13 +125,6 @@ public class MeetingService implements MessageListener {
         return user;
     }
 
-    /**
-     * Remove the meetings that have ended from the list of running meetings.
-     */
-    public void removeExpiredMeetings() {
-        handle(new RemoveExpiredMeetings());
-    }
-
     /**
      * Remove registered users who did not successfully joined the meeting.
      */
@@ -162,7 +149,6 @@ public class MeetingService implements MessageListener {
                 }
             }
         }
-        handle(new RemoveExpiredMeetings());
     }
 
     private void kickOffProcessingOfRecording(Meeting m) {
@@ -203,77 +189,6 @@ public class MeetingService implements MessageListener {
         }
     }
 
-    private void checkAndRemoveExpiredMeetings() {
-        for (Meeting m : meetings.values()) {
-            if (m.hasExpired(defaultMeetingExpireDuration)) {
-                Map<String, Object> logData = new HashMap<String, Object>();
-                logData.put("meetingId", m.getInternalId());
-                logData.put("externalMeetingId", m.getExternalId());
-                logData.put("name", m.getName());
-                logData.put("event", "removing_meeting");
-                logData.put("description", "Meeting has expired.");
-
-                Gson gson = new Gson();
-                String logStr = gson.toJson(logData);
-                log.info("Removing expired meeting: data={}", logStr);
-
-                processMeetingForRemoval(m);
-                continue;
-            }
-
-            if (m.isForciblyEnded()) {
-                Map<String, Object> logData = new HashMap<String, Object>();
-                logData.put("meetingId", m.getInternalId());
-                logData.put("externalMeetingId", m.getExternalId());
-                logData.put("name", m.getName());
-                logData.put("event", "removing_meeting");
-                logData.put("description", "Meeting forcefully ended.");
-
-                Gson gson = new Gson();
-                String logStr = gson.toJson(logData);
-
-                log.info("Removing ended meeting: data={}", logStr);
-                processMeetingForRemoval(m);
-                continue;
-            }
-
-            if (m.wasNeverJoined(defaultMeetingCreateJoinDuration)) {
-                Map<String, Object> logData = new HashMap<String, Object>();
-                logData.put("meetingId", m.getInternalId());
-                logData.put("externalMeetingId", m.getExternalId());
-                logData.put("name", m.getName());
-                logData.put("event", "removing_meeting");
-                logData.put("description", "Meeting has not been joined.");
-
-                Gson gson = new Gson();
-                String logStr = gson.toJson(logData);
-
-                log.info("Removing un-joined meeting: data={}", logStr);
-
-                destroyMeeting(m.getInternalId());
-                meetings.remove(m.getInternalId());
-                removeUserSessions(m.getInternalId());
-                continue;
-            }
-
-            if (m.hasExceededDuration()) {
-                Map<String, Object> logData = new HashMap<String, Object>();
-                logData.put("meetingId", m.getInternalId());
-                logData.put("externalMeetingId", m.getExternalId());
-                logData.put("name", m.getName());
-                logData.put("event", "removing_meeting");
-                logData.put("description", "Meeting exceeded duration.");
-
-                Gson gson = new Gson();
-                String logStr = gson.toJson(logData);
-
-                log.info("Removing past duration meeting: data={}", logStr);
-
-                endMeeting(m.getInternalId());
-            }
-        }
-    }
-
     private void destroyMeeting(String meetingID) {
         messagingService.destroyMeeting(meetingID);
     }
@@ -608,12 +523,10 @@ public class MeetingService implements MessageListener {
         Meeting m = getMeeting(message.meetingId);
         if (m != null) {
             m.setForciblyEnded(true);
-            if (removeMeetingWhenEnded) {
-                processRecording(m.getInternalId());
-                destroyMeeting(m.getInternalId());
-                meetings.remove(m.getInternalId());
-                removeUserSessions(m.getInternalId());
-            }
+            processRecording(m.getInternalId());
+            destroyMeeting(m.getInternalId());
+            meetings.remove(m.getInternalId());
+            removeUserSessions(m.getInternalId());
         }
     }
 
@@ -947,8 +860,6 @@ public class MeetingService implements MessageListener {
                     userSharedWebcam((UserSharedWebcam) message);
                 } else if (message instanceof UserUnsharedWebcam) {
                     userUnsharedWebcam((UserUnsharedWebcam) message);
-                } else if (message instanceof RemoveExpiredMeetings) {
-                    checkAndRemoveExpiredMeetings();
                 } else if (message instanceof CreateMeeting) {
                     processCreateMeeting((CreateMeeting) message);
                 } else if (message instanceof EndMeeting) {
@@ -997,18 +908,9 @@ public class MeetingService implements MessageListener {
 
     public void stop() {
         processMessage = false;
-        cleaner.stop();
         registeredUserCleaner.stop();
     }
 
-    public void setDefaultMeetingCreateJoinDuration(int expiration) {
-        this.defaultMeetingCreateJoinDuration = expiration;
-    }
-
-    public void setDefaultMeetingExpireDuration(int meetingExpiration) {
-        this.defaultMeetingExpireDuration = meetingExpiration;
-    }
-
     public void setRecordingService(RecordingService s) {
         recordingService = s;
     }
@@ -1017,17 +919,6 @@ public class MeetingService implements MessageListener {
         messagingService = mess;
     }
 
-    public void setExpiredMeetingCleanupTimerTask(
-            ExpiredMeetingCleanupTimerTask c) {
-        cleaner = c;
-        cleaner.setMeetingService(this);
-        cleaner.start();
-    }
-
-    public void setRemoveMeetingWhenEnded(boolean s) {
-        removeMeetingWhenEnded = s;
-    }
-
     public void setRegisteredUserCleanupTimerTask(
             RegisteredUserCleanupTimerTask c) {
         registeredUserCleaner = c;
diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/api/messaging/messages/RemoveExpiredMeetings.java b/bigbluebutton-web/src/java/org/bigbluebutton/api/messaging/messages/RemoveExpiredMeetings.java
deleted file mode 100755
index 6282e017ed9db62f01c5395a315715c54f72ab8b..0000000000000000000000000000000000000000
--- a/bigbluebutton-web/src/java/org/bigbluebutton/api/messaging/messages/RemoveExpiredMeetings.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.bigbluebutton.api.messaging.messages;
-
-public class RemoveExpiredMeetings implements IMessage {
-
-}
diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/web/services/ExpiredMeetingCleanupTimerTask.java b/bigbluebutton-web/src/java/org/bigbluebutton/web/services/ExpiredMeetingCleanupTimerTask.java
deleted file mode 100644
index db8b5b8b2c47fe58a95673e8be4d209dfa977a77..0000000000000000000000000000000000000000
--- a/bigbluebutton-web/src/java/org/bigbluebutton/web/services/ExpiredMeetingCleanupTimerTask.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
-* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
-* 
-* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
-*
-* This program is free software; you can redistribute it and/or modify it under the
-* terms of the GNU Lesser General Public License as published by the Free Software
-* Foundation; either version 3.0 of the License, or (at your option) any later
-* version.
-* 
-* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
-* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License along
-* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-package org.bigbluebutton.web.services;
-
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import org.bigbluebutton.api.MeetingService;
-
-public class ExpiredMeetingCleanupTimerTask {
-
-	private MeetingService service;
-	private ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
-	private long runEvery = 60000;
-
-	public void setMeetingService(MeetingService svc) {
-		this.service = svc;
-	}
-	
-	public void start() {
-		scheduledThreadPool.scheduleWithFixedDelay(new CleanupTask(), 60000, runEvery, TimeUnit.MILLISECONDS);		
-	}
-	
-	public void stop() {
-		scheduledThreadPool.shutdownNow();
-	}
-	
-	public void setRunEvery(long v) {
-		runEvery = v;
-	}
-	
-	private class CleanupTask implements Runnable {
-        public void run() {
-        	service.removeExpiredMeetings();
-        }
-    }
-}
\ No newline at end of file