diff --git a/releasenotes/notes/stale-action-plan-b6a6b08df873c128.yaml b/releasenotes/notes/stale-action-plan-b6a6b08df873c128.yaml
index 1ddf8cdc9..9ef9a4c77 100644
--- a/releasenotes/notes/stale-action-plan-b6a6b08df873c128.yaml
+++ b/releasenotes/notes/stale-action-plan-b6a6b08df873c128.yaml
@@ -1,4 +1,4 @@
 ---
 features:
-  - Add superseded state for an action plan if the cluster data model has
-    changed after it has been created.
+  - Check the creation time of the action plan, 
+    and set its state to SUPERSEDED if it has expired.
diff --git a/watcher/conf/decision_engine.py b/watcher/conf/decision_engine.py
index 4ff90da22..162dc29d4 100644
--- a/watcher/conf/decision_engine.py
+++ b/watcher/conf/decision_engine.py
@@ -42,6 +42,15 @@ WATCHER_DECISION_ENGINE_OPTS = [
                required=True,
                help='The maximum number of threads that can be used to '
                     'execute strategies'),
+    cfg.IntOpt('action_plan_expiry',
+               default=24,
+               help='An expiry timespan(hours). Watcher invalidates any '
+                    'action plan for which its creation time '
+                    '-whose number of hours has been offset by this value-'
+                    ' is older that the current time.'),
+    cfg.IntOpt('check_periodic_interval',
+               default=30*60,
+               help='Interval (in seconds) for checking action plan expiry.')
 ]
 
 WATCHER_CONTINUOUS_OPTS = [
diff --git a/watcher/decision_engine/scheduling.py b/watcher/decision_engine/scheduling.py
index d5fa1f965..4ef0481cd 100644
--- a/watcher/decision_engine/scheduling.py
+++ b/watcher/decision_engine/scheduling.py
@@ -19,12 +19,17 @@ import datetime
 import eventlet
 from oslo_log import log
 
+from watcher.common import context
 from watcher.common import exception
 from watcher.common import scheduling
 
 from watcher.decision_engine.model.collector import manager
+from watcher import objects
+
+from watcher import conf
 
 LOG = log.getLogger(__name__)
+CONF = conf.CONF
 
 
 class DecisionEngineSchedulingService(scheduling.BackgroundSchedulerService):
@@ -73,9 +78,20 @@ class DecisionEngineSchedulingService(scheduling.BackgroundSchedulerService):
 
         return _sync
 
+    def add_checkstate_job(self):
+        # 30 minutes interval
+        interval = CONF.watcher_decision_engine.check_periodic_interval
+        ap_manager = objects.action_plan.StateManager()
+        if CONF.watcher_decision_engine.action_plan_expiry != 0:
+            self.add_job(ap_manager.check_expired, 'interval',
+                         args=[context.make_context()],
+                         seconds=interval,
+                         next_run_time=datetime.datetime.now())
+
     def start(self):
         """Start service."""
         self.add_sync_jobs()
+        self.add_checkstate_job()
         super(DecisionEngineSchedulingService, self).start()
 
     def stop(self):
diff --git a/watcher/objects/action_plan.py b/watcher/objects/action_plan.py
index b08ec3319..dc171f263 100644
--- a/watcher/objects/action_plan.py
+++ b/watcher/objects/action_plan.py
@@ -71,15 +71,19 @@ state may be one of the following:
    **RECOMMENDED** state and was superseded by the
    :ref:`Administrator <administrator_definition>`
 """
+import datetime
 
 from watcher.common import exception
 from watcher.common import utils
+from watcher import conf
 from watcher.db import api as db_api
 from watcher import notifications
 from watcher import objects
 from watcher.objects import base
 from watcher.objects import fields as wfields
 
+CONF = conf.CONF
+
 
 class State(object):
     RECOMMENDED = 'RECOMMENDED'
@@ -317,3 +321,18 @@ class ActionPlan(base.WatcherPersistentObject, base.WatcherObject,
             notifications.action_plan.send_delete(self._context, self)
 
         _notify()
+
+
+class StateManager(object):
+    def check_expired(self, context):
+        action_plan_expiry = (
+            CONF.watcher_decision_engine.action_plan_expiry)
+        date_created = datetime.datetime.utcnow() - datetime.timedelta(
+            hours=action_plan_expiry)
+        filters = {'state__eq': State.RECOMMENDED,
+                   'created_at__lt': date_created}
+        action_plans = objects.ActionPlan.list(
+            context, filters=filters, eager=True)
+        for action_plan in action_plans:
+            action_plan.state = State.SUPERSEDED
+            action_plan.save()
diff --git a/watcher/tests/decision_engine/test_scheduling.py b/watcher/tests/decision_engine/test_scheduling.py
index f414ad300..d4a057cd9 100644
--- a/watcher/tests/decision_engine/test_scheduling.py
+++ b/watcher/tests/decision_engine/test_scheduling.py
@@ -48,7 +48,7 @@ class TestDecisionEngineSchedulingService(base.TestCase):
 
         m_start.assert_called_once_with(scheduler)
         jobs = scheduler.get_jobs()
-        self.assertEqual(1, len(jobs))
+        self.assertEqual(2, len(jobs))
 
         job = jobs[0]
         self.assertTrue(bool(fake_collector.cluster_data_model))
@@ -77,7 +77,7 @@ class TestDecisionEngineSchedulingService(base.TestCase):
 
         m_start.assert_called_once_with(scheduler)
         jobs = scheduler.get_jobs()
-        self.assertEqual(1, len(jobs))
+        self.assertEqual(2, len(jobs))
 
         job = jobs[0]
         job.func()
diff --git a/watcher/tests/objects/test_action_plan.py b/watcher/tests/objects/test_action_plan.py
index 7c8ee0ecc..a06c94813 100644
--- a/watcher/tests/objects/test_action_plan.py
+++ b/watcher/tests/objects/test_action_plan.py
@@ -19,12 +19,16 @@ import iso8601
 import mock
 
 from watcher.common import exception
+from watcher.common import utils as common_utils
+from watcher import conf
 from watcher.db.sqlalchemy import api as db_api
 from watcher import notifications
 from watcher import objects
 from watcher.tests.db import base
 from watcher.tests.db import utils
 
+CONF = conf.CONF
+
 
 class TestActionPlanObject(base.DbTestCase):
 
@@ -290,3 +294,31 @@ class TestCreateDeleteActionPlanObject(base.DbTestCase):
         m_destroy_efficacy_indicator.assert_called_once_with(
             efficacy_indicator['uuid'])
         self.assertEqual(self.context, action_plan._context)
+
+
+@mock.patch.object(notifications.action_plan, 'send_update', mock.Mock())
+class TestStateManager(base.DbTestCase):
+
+    def setUp(self):
+        super(TestStateManager, self).setUp()
+        self.state_manager = objects.action_plan.StateManager()
+
+    def test_check_expired(self):
+        CONF.set_default('action_plan_expiry', 0,
+                         group='watcher_decision_engine')
+        strategy_1 = utils.create_test_strategy(
+            uuid=common_utils.generate_uuid())
+        audit_1 = utils.create_test_audit(
+            uuid=common_utils.generate_uuid())
+        action_plan_1 = utils.create_test_action_plan(
+            state=objects.action_plan.State.RECOMMENDED,
+            uuid=common_utils.generate_uuid(),
+            audit_id=audit_1.id,
+            strategy_id=strategy_1.id)
+
+        self.state_manager.check_expired(self.context)
+
+        action_plan = objects.action_plan.ActionPlan.get_by_uuid(
+            self.context, action_plan_1.uuid)
+        self.assertEqual(objects.action_plan.State.SUPERSEDED,
+                         action_plan.state)