diff --git a/app/views/admin/AnalyticsSubscriptionsView.coffee b/app/views/admin/AnalyticsSubscriptionsView.coffee
index e308707f0..cceebef4f 100644
--- a/app/views/admin/AnalyticsSubscriptionsView.coffee
+++ b/app/views/admin/AnalyticsSubscriptionsView.coffee
@@ -47,7 +47,20 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
     return unless me.isAdmin()
     @resetSubscriptionsData()
     @getSubscribers()
-    @getSubscriptions()
+    @getCancellations (cancellations) =>
+      @getSubscriptions(cancellations)
+
+  getCancellations: (done) ->
+    options =
+      url: '/db/subscription/-/cancellations'
+      method: 'GET'
+    options.error = (model, response, options) =>
+      return if @destroyed
+      console.error 'Failed to get cancellations', response
+    options.success = (cancellations, response, options) =>
+      return if @destroyed
+      done(cancellations)
+    @supermodel.addRequestResource('get_cancellations', options, 0).load()
 
   getSubscribers: ->
     options =
@@ -67,7 +80,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
       @render?()
     @supermodel.addRequestResource('get_subscribers', options, 0).load()
 
-  getSubscriptions: ->
+  getSubscriptions: (cancellations=[]) ->
     options =
       url: '/db/subscription/-/subscriptions'
       method: 'GET'
@@ -83,14 +96,18 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
         subDayMap[startDay] ?= {}
         subDayMap[startDay]['start'] ?= 0
         subDayMap[startDay]['start']++
-        if cancelDay = sub?.cancel?.substring(0, 10)
-          subDayMap[cancelDay] ?= {}
-          subDayMap[cancelDay]['cancel'] ?= 0
-          subDayMap[cancelDay]['cancel']++
         if endDay = sub?.end?.substring(0, 10)
           subDayMap[endDay] ?= {}
           subDayMap[endDay]['end'] ?= 0
           subDayMap[endDay]['end']++
+        for cancellation in cancellations
+          if cancellation.subID is sub.subID
+            cancelDay = cancellation.cancel.substring(0, 10)
+            subDayMap[cancelDay] ?= {}
+            subDayMap[cancelDay]['cancel'] ?= 0
+            subDayMap[cancelDay]['cancel']++
+            break
+
       today = new Date().toISOString().substring(0, 10)
       for day of subDayMap
         continue if day > today
diff --git a/server/payments/subscription_handler.coffee b/server/payments/subscription_handler.coffee
index 5c81df700..c49f4c8bd 100644
--- a/server/payments/subscription_handler.coffee
+++ b/server/payments/subscription_handler.coffee
@@ -24,10 +24,53 @@ class SubscriptionHandler extends Handler
     console.warn "Subscription Error: #{user.get('slug')} (#{user._id}): '#{msg}'"
 
   getByRelationship: (req, res, args...) ->
+    return @getCancellations(req, res) if args[1] is 'cancellations'
     return @getSubscribers(req, res) if args[1] is 'subscribers'
     return @getSubscriptions(req, res) if args[1] is 'subscriptions'
     super(arguments...)
 
+  getCancellations: (req, res) =>
+    return @sendForbiddenError(res) unless req.user and req.user.isAdmin()
+    @cancellations = []
+    nextBatch = (starting_after, done) =>
+      options = limit: 100
+      options.starting_after = starting_after if starting_after
+      stripe.customers.list options, (err, customers) =>
+        return done(err) if err
+
+        for customer in customers.data
+          continue unless customer?.subscriptions?.data?.length > 0
+          for subscription in customer.subscriptions.data
+            continue unless subscription.plan.id is 'basic'
+
+            amount = subscription.plan.amount
+            if subscription?.discount?.coupon?
+              if subscription.discount.coupon.percent_off
+                amount = amount *  (100 - subscription.discount.coupon.percent_off) / 100;
+              else if subscription.discount.coupon.amount_off
+                amount -= subscription.discount.coupon.amount_off
+            else if customer.discount?.coupon?
+              if customer.discount.coupon.percent_off
+                amount = amount *  (100 - customer.discount.coupon.percent_off) / 100
+              else if customer.discount.coupon.amount_off
+                amount -= customer.discount.coupon.amount_off
+
+            continue unless amount > 0
+
+            if subscription.cancel_at_period_end
+              @cancellations.push
+                cancel: new Date(subscription.canceled_at * 1000)
+                subID: subscription.id
+
+        if customers.has_more
+          # console.log 'Fetching more customers', Object.keys(@cancellations).length
+          return nextBatch(customers.data[customers.data.length - 1].id, done)
+        else
+          return done()
+    nextBatch null, (err) =>
+      return @sendDatabaseError(res, err) if err
+      @sendSuccess(res, @cancellations)
+
   getSubscribers: (req, res) ->
     return @sendForbiddenError(res) unless req.user and req.user.isAdmin()
 
@@ -102,8 +145,6 @@ class SubscriptionHandler extends Handler
     # return @sendSuccess(res, @subs) unless _.isEmpty(@subs)
     @subMap = {}
 
-    console.log 'Fetching invoices...'
-
     processInvoices = (starting_after, done) =>
       options = limit: 100
       options.starting_after = starting_after if starting_after
@@ -124,49 +165,27 @@ class SubscriptionHandler extends Handler
               last: invoiceDate
               customerID: invoice.customer
         if invoices.has_more
-          console.log 'Fetching more invoices', Object.keys(@subMap).length
+          # console.log 'Fetching more invoices', Object.keys(@subMap).length
           return processInvoices(invoices.data[invoices.data.length - 1].id, done)
         else
           return done()
 
     processInvoices null, (err) =>
       return @sendDatabaseError(res, err) if err
-
-      console.log 'Checking cancelled subscriptions...'
-
-      createCheckCancelledFn = (customerID, subscriptionID) =>
-        (done) =>
-          stripe.customers.retrieveSubscription customerID, subscriptionID, (err, subscription) =>
-            return done() if err
-            if subscription?.cancel_at_period_end
-              @subMap[subscriptionID].cancel = new Date(subscription.canceled_at * 1000)
-            done()
-
-      tasks = []
+      @subs = []
       for subID of @subMap
-        expectedLastPayment = new Date(@subMap[subID].last)
-        expectedLastPayment.setUTCFullYear(new Date().getUTCFullYear())
-        expectedLastPayment.setUTCMonth(new Date().getUTCMonth() - 1)
-        expectedLastPayment.setUTCDate(new Date().getUTCDate() - 8) # In case last payment had some retries
-        if @subMap[subID].last > expectedLastPayment
-          tasks.push createCheckCancelledFn(@subMap[subID].customerID, subID)
-
-      async.parallel tasks, (err, results) =>
-        return @sendDatabaseError(res, err) if err
-        @subs = []
-        for subID of @subMap
-          sub =
-            start: @subMap[subID].first
-            subID: subID
-            customerID: @subMap[subID].customerID
-          sub.cancel = @subMap[subID].cancel if @subMap[subID].cancel
-          oneMonthAgo = new Date()
-          oneMonthAgo.setUTCMonth(oneMonthAgo.getUTCMonth() - 1)
-          if @subMap[subID].last < oneMonthAgo
-            sub.end = new Date(@subMap[subID].last)
-            sub.end.setUTCMonth(sub.end.getUTCMonth() + 1)
-          @subs.push sub
-        @sendSuccess(res, @subs)
+        sub =
+          start: @subMap[subID].first
+          subID: subID
+          customerID: @subMap[subID].customerID
+        sub.cancel = @subMap[subID].cancel if @subMap[subID].cancel
+        oneMonthAgo = new Date()
+        oneMonthAgo.setUTCMonth(oneMonthAgo.getUTCMonth() - 1)
+        if @subMap[subID].last < oneMonthAgo
+          sub.end = new Date(@subMap[subID].last)
+          sub.end.setUTCMonth(sub.end.getUTCMonth() + 1)
+        @subs.push sub
+      @sendSuccess(res, @subs)
 
   subscribeUser: (req, user, done) ->
     if (not req.user) or req.user.isAnonymous() or user.isAnonymous()