   (toString [this] 
     (str "'" state "' is not started (to start all the states call mount/start)")))
 
-;;TODO validate stop and the fact that start and stop are fns
-(defn- validate [{:keys [start stop]}]
+;;TODO validate the whole lifecycle
+(defn- validate [{:keys [start stop suspend resume] :as lifecycle}]
   (when-not start 
     (throw (IllegalArgumentException. "can't start a stateful thing without a start function. (i.e. missing :start fn)")))
-  {:start start :stop stop})
+  (when (and suspend (not resume))
+    (throw (IllegalArgumentException. "suspendable state should have a resume function (i.e. missing :resume fn)"))))
 
 (defmacro defstate [state & body]
-  (let [[state [c cf d df]] (macro/name-with-attributes state body)
-        {:keys [start stop]} (validate {c cf d df})]
+  (let [[state params] (macro/name-with-attributes state body)
+        {:keys [start stop suspend resume] :as lifecycle} (apply hash-map params)]
+    (validate lifecycle)
     (let [s-meta (-> {:mount-state mount-state
                       :order (make-state-seq state)
                       :start `(fn [] (~@start)) 
                       :started? false}
-                     (cond-> df (assoc :stop `(fn [] (~@stop)))))]
+                     (cond-> stop (assoc :stop `(fn [] (~@stop))))
+                     (cond-> suspend (assoc :suspend `(fn [] (~@suspend))))
+                     (cond-> resume (assoc :resume `(fn [] (~@resume)))))]
       `(defonce ~(with-meta state (merge (meta state) s-meta))
          (NotStartedState. ~(str state))))))
 
-(defn- up [var {:keys [ns name start started?]}]
+(defn- up [var {:keys [ns name start started? resume suspended?]}]
   (when-not started?
-    (info ">> starting.. " name)
-    (let [s (try (start) 
-                 (catch Throwable t 
+    (let [s (try (if suspended?
+                   (do (info ">> resuming.. " name)
+                       (resume))
+                   (do (info ">> starting.. " name)
+                       (start)))
+                 (catch Throwable t
                    (throw (RuntimeException. (str "could not start [" name "] due to") t))))]
       (intern ns (symbol name) s)
-      (alter-meta! var assoc :started? true))))
+      (alter-meta! var assoc :started? true :suspended? false))))
 
-(defn- down [var {:keys [ns name stop started?]}]
-  (when started?
+(defn- down [var {:keys [ns name stop started? suspended?]}]
+  (when (or started? suspended?)
     (info "<< stopping.. " name)
     (when stop 
       (try
         (stop)
-        (catch Throwable t 
+        (catch Throwable t
           (throw (RuntimeException. (str "could not stop [" name "] due to") t)))))
     (intern ns (symbol name) (NotStartedState. name)) ;; (!) if a state does not have :stop when _should_ this might leak
-    (alter-meta! var assoc :started? false)))
+    (alter-meta! var assoc :started? false :suspended? false)))
+
+(defn- sigstop [var {:keys [ns name started? suspend resume]}]
+  (when (and started? resume)        ;; can't have suspend without resume, but the reverse is possible
+    (info ">> suspending.. " name)
+    (when suspend                    ;; don't suspend if there is only resume function (just mark it :suspended?)
+      (let [s (try (suspend)
+                   (catch Throwable t
+                     (throw (RuntimeException. (str "could not suspend [" name "] due to") t))))]
+        (intern ns (symbol name) s)))
+    (alter-meta! var assoc :started? false :suspended? true)))
+
+(defn- sigcont [var {:keys [ns name start started? resume suspended?]}]
+  (when (instance? NotStartedState var)
+    (throw (RuntimeException. (str "could not resume [" name "] since it is stoppped (i.e. not suspended)"))))
+  (when suspended?
+    (info ">> resuming.. " name)
+    (let [s (try (resume)
+                 (catch Throwable t
+                   (throw (RuntimeException. (str "could not resume [" name "] due to") t))))]
+      (intern ns (symbol name) s)
+      (alter-meta! var assoc :started? true :suspended? false))))
 
 ;;TODO args might need more thinking
 (defn args [] @-args)

    (doall (map rollback! states)) ;; restore to origin from "start-with"
    :stopped))

(defn start-with-args [xs & states]
  (reset! -args xs)
  (if (first states)

       (map second)
       (filter mount-state?)))

;;TODO ns based for now. need to be _state_ based
(defn- add-deps [{:keys [ns] :as state} all]
  (let [refers (ns-refers ns)
