             assertionFailure("Failure to create data from entry string")
             return
         }
-        self.uploadData(data)
-    }
-
-    private func newClearTimer() -> dispatch_source_t {
-        return dispatchRepeatingTimer(delay: 5.0, interval: 15.0, tolerance: 5.0, handler: { self.clearCompleted() })
-    }
-
-    private func uploadData(data: NSData) {
-        dispatch_async(self.lock, {
-            let task = self.session.uploadTaskWithRequest(self.request, fromData: data, completionHandler: { _, response, _ in
-                if !self.successCodes.contains((response as? NSHTTPURLResponse)?.statusCode ?? -1) {
-                    self.uploadData(data)
-                }
-            })
-            if !self.suspended {
+        self.cache.addData(data)
+        self.timer.fire() // or should we just wait for the next timer firing?
+    }
+
+    @objc private func upload(timer: NSTimer?) {
+        dispatch_async(LK_LOGKIT_QUEUE, {
+            let pendingUploads = self.cache.reserveData()
+            for (id, data) in pendingUploads {
+                let task = self.session.uploadTaskWithRequest(self.request, fromData: data, completionHandler: { _, response, _ in
+                    if self.successCodes.contains((response as? NSHTTPURLResponse)?.statusCode ?? -1) {
+                        self.cache.completeProgressOnIDs([id]) //TODO: more efficient releasing
+                    } else {
+                        self.cache.cancelProgressOnIDs([id])
+                    }
+                })
                 task.resume()
             }
         })
-    }
-
-    private func clearCompleted() {
-        dispatch_barrier_async(self.lock, {
-            self.pending = self.pending.filter({ $0.state == .Running || $0.state == .Suspended })
-        })
-    }
-
-    public func suspend() {
-        if !self.suspended {
-            dispatch_source_cancel(self.clearTimer)
-            self.suspended = true
-            dispatch_barrier_async(self.lock, {
-                self.pending.filter({ $0.state == .Running }).map({ task -> Void in task.suspend() })
-            })
-        }
-    }
-
-    public func resume() {
-        if self.suspended {
-            self.suspended = false
-            self.clearTimer = self.newClearTimer()
-            dispatch_resume(self.clearTimer)
-            dispatch_barrier_async(self.lock, {
-                self.pending.filter({ $0.state == .Suspended }).map({ task -> Void in task.resume() })
-            })
-        }
     }
 
 }

    }

    deinit {
        if !self.suspended {
            dispatch_source_cancel(self.clearTimer)
        }
        self.session.finishTasksAndInvalidate()
    }


    public var entryFormatter: LXEntryFormatter
    public let requiresNewlines: Bool = false

    private let successCodes: Set<Int>
    private let session: NSURLSession
    private let request: NSURLRequest

    private let cache: LXPersistedCache = LXPersistedCache(timeoutInterval: 50)
    private lazy var timer: NSTimer = {
        let timer = NSTimer.scheduledTimerWithTimeInterval(60, target: self, selector: "upload:", userInfo: nil, repeats: true)
        timer.tolerance = 10
        return timer
    }()

    public init(
        request: NSURLRequest,
        successCodes: Set<Int> = defaultSuccessCodes,
        sessionConfiguration: NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration(),
        minimumLogLevel: LXLogLevel = .All,
        dateFormatter: LXDateFormatter = LXDateFormatter.standardFormatter(),
