diff --git a/lib/plugin/instance.rb b/lib/plugin/instance.rb
index 8c0370c2f..42b2e8bf9 100644
--- a/lib/plugin/instance.rb
+++ b/lib/plugin/instance.rb
@@ -217,9 +217,6 @@ class Plugin::Instance
       DiscoursePluginRegistry.register_glob(root_path, 'hbs')
     end
 
-    # Automatically include all rake tasks
-    Rake.add_rakelib "#{File.dirname(path)}/lib/tasks"
-
     self.instance_eval File.read(path), path
     if auto_assets = generate_automatic_assets!
       assets.concat auto_assets.map{|a| [a]}
@@ -227,10 +224,18 @@ class Plugin::Instance
 
     register_assets! unless assets.blank?
 
-    # TODO possibly amend this to a rails engine
+    # TODO: possibly amend this to a rails engine
+
+    # Automatically include assets
     Rails.configuration.assets.paths << auto_generated_path
     Rails.configuration.assets.paths << File.dirname(path) + "/assets"
 
+    # Automatically include rake tasks
+    Rake.add_rakelib(File.dirname(path) + "/lib/tasks")
+
+    # Automatically include migrations
+    Rails.configuration.paths["db/migrate"] << File.dirname(path) + "/db/migrate"
+
     public_data = File.dirname(path) + "/public"
     if Dir.exists?(public_data)
       target = Rails.root.to_s + "/public/plugins/"
diff --git a/plugins/poll/assets/javascripts/components/poll-results-number.js.es6 b/plugins/poll/assets/javascripts/components/poll-results-number.js.es6
index 4e7c6b35f..da48d4abb 100644
--- a/plugins/poll/assets/javascripts/components/poll-results-number.js.es6
+++ b/plugins/poll/assets/javascripts/components/poll-results-number.js.es6
@@ -12,9 +12,9 @@ export default Em.Component.extend({
   }.property("poll.options.@each.{html,votes}"),
 
   average: function() {
-    const total_votes = this.get("poll.total_votes");
-    return total_votes == 0 ? 0 : round(this.get("totalScore") / total_votes, -2);
-  }.property("totalScore", "poll.total_votes"),
+    const voters = this.get("poll.voters");
+    return voters === 0 ? 0 : round(this.get("totalScore") / voters, -2);
+  }.property("totalScore", "poll.voters"),
 
   averageRating: function() {
     return I18n.t("poll.average_rating", { average: this.get("average") });
diff --git a/plugins/poll/assets/javascripts/components/poll-results-standard.js.es6 b/plugins/poll/assets/javascripts/components/poll-results-standard.js.es6
index 21f213d83..d9268f2fe 100644
--- a/plugins/poll/assets/javascripts/components/poll-results-standard.js.es6
+++ b/plugins/poll/assets/javascripts/components/poll-results-standard.js.es6
@@ -3,7 +3,7 @@ export default Em.Component.extend({
   classNames: ["results"],
 
   options: function() {
-    const totalVotes = this.get("poll.total_votes"),
+    const totalVotes = this.get("poll.voters"),
           backgroundColor = this.get("poll.background");
 
     this.get("poll.options").forEach(option => {
@@ -20,6 +20,6 @@ export default Em.Component.extend({
     });
 
     return this.get("poll.options");
-  }.property("poll.total_votes", "poll.options.[]")
+  }.property("poll.voters", "poll.options.[]")
 
 });
diff --git a/plugins/poll/assets/javascripts/controllers/poll.js.es6 b/plugins/poll/assets/javascripts/controllers/poll.js.es6
index cfbd9b862..418156ace 100644
--- a/plugins/poll/assets/javascripts/controllers/poll.js.es6
+++ b/plugins/poll/assets/javascripts/controllers/poll.js.es6
@@ -13,7 +13,7 @@ export default Em.Controller.extend({
   //   - user wants to see the results
   showingResults: Em.computed.or("isClosed", "post.topic.closed", "post.topic.archived", "showResults"),
 
-  showResultsDisabled: Em.computed.equal("poll.total_votes", 0),
+  showResultsDisabled: Em.computed.equal("poll.voters", 0),
   hideResultsDisabled: Em.computed.alias("isClosed"),
 
   poll: function() {
@@ -37,10 +37,6 @@ export default Em.Controller.extend({
     return _.map(this.get("poll.options").filterBy("selected"), o => o.get("id"));
   }.property("poll.options.@each.selected"),
 
-  totalVotesText: function() {
-    return I18n.t("poll.total_votes", { count: this.get("poll.total_votes") });
-  }.property("poll.total_votes"),
-
   min: function() {
     let min = parseInt(this.get("poll.min"), 10);
     if (isNaN(min) || min < 1) { min = 1; }
diff --git a/plugins/poll/assets/javascripts/discourse/templates/poll.hbs b/plugins/poll/assets/javascripts/discourse/templates/poll.hbs
index 22bedde10..17f2c09b4 100644
--- a/plugins/poll/assets/javascripts/discourse/templates/poll.hbs
+++ b/plugins/poll/assets/javascripts/discourse/templates/poll.hbs
@@ -14,8 +14,6 @@
   {{/if}}
 </div>
 
-<p>{{totalVotesText}}</p>
-
 {{#if isMultiple}}
   <p>{{multipleHelpText}}</p>
   {{d-button class="cast-votes" title="poll.cast-votes.title" label="poll.cast-votes.label" disabled=castVotesDisabled action="castVotes"}}
diff --git a/plugins/poll/assets/javascripts/poll_dialect.js b/plugins/poll/assets/javascripts/poll_dialect.js
index e752762fa..d876dbe8c 100644
--- a/plugins/poll/assets/javascripts/poll_dialect.js
+++ b/plugins/poll/assets/javascripts/poll_dialect.js
@@ -98,10 +98,8 @@
       }
 
       // that's our poll!
-      var result = ["div", attributes].concat(contents);
-
-      // add a small paragraph displaying the total number of votes
-      result.push(["p", I18n.t("poll.total_votes", { count: 0 })]);
+      var pollContainer = ["div", { "class": "poll-container" }].concat(contents);
+      var result = ["div", attributes, pollContainer];
 
       // add some information when type is "multiple"
       if (attributes[DATA_PREFIX + "type"] === "multiple") {
@@ -144,6 +142,7 @@
   });
 
   Discourse.Markdown.whiteListTag("div", "class", "poll");
+  Discourse.Markdown.whiteListTag("div", "class", "poll-container");
   Discourse.Markdown.whiteListTag("div", "data-*");
 
   Discourse.Markdown.whiteListTag("a", "class", /^button (cast-votes|toggle-results)/);
diff --git a/plugins/poll/assets/stylesheets/poll.scss b/plugins/poll/assets/stylesheets/poll.scss
index ad35ea9a9..95b71a196 100644
--- a/plugins/poll/assets/stylesheets/poll.scss
+++ b/plugins/poll/assets/stylesheets/poll.scss
@@ -59,7 +59,7 @@ div.poll {
   }
 
   .poll-container {
-    margin: 0;
+    margin: 0 0 5px;
     span {
       font-size: 1.125em;
       line-height: 2
diff --git a/plugins/poll/config/locales/client.en.yml b/plugins/poll/config/locales/client.en.yml
index 24b5dc2f1..c0920196a 100644
--- a/plugins/poll/config/locales/client.en.yml
+++ b/plugins/poll/config/locales/client.en.yml
@@ -8,7 +8,7 @@
 en:
   js:
     poll:
-      total_votes:
+      voters:
         zero: "No votes yet. Want to be the first?"
         one: "There's only 1 vote."
         other: "There are %{count} total votes."
diff --git a/plugins/poll/config/locales/client.es.yml b/plugins/poll/config/locales/client.es.yml
index a64fc9ffd..d51dc84f1 100644
--- a/plugins/poll/config/locales/client.es.yml
+++ b/plugins/poll/config/locales/client.es.yml
@@ -8,7 +8,7 @@
 es:
   js:
     poll:
-      total_votes:
+      voters:
         zero: "Sin votos todavía. ¿Quieres ser el primero?"
         one: "Sólo hay 1 voto."
         other: "Hay %{count} votos en total."
diff --git a/plugins/poll/config/locales/client.fr.yml b/plugins/poll/config/locales/client.fr.yml
index ad8450688..5e72189eb 100644
--- a/plugins/poll/config/locales/client.fr.yml
+++ b/plugins/poll/config/locales/client.fr.yml
@@ -8,7 +8,7 @@
 fr:
   js:
     poll:
-      total_votes:
+      voters:
         zero: "Pas encore de votes. Soyez le premier !"
         one: "Il n'y a qu'un vote."
         other: "Il y a au total %{count} votes."
diff --git a/plugins/poll/db/migrate/20150501152228_rename_total_votes_to_voters.rb b/plugins/poll/db/migrate/20150501152228_rename_total_votes_to_voters.rb
new file mode 100644
index 000000000..902c84ded
--- /dev/null
+++ b/plugins/poll/db/migrate/20150501152228_rename_total_votes_to_voters.rb
@@ -0,0 +1,29 @@
+class RenameTotalVotesToVoters < ActiveRecord::Migration
+
+  def up
+    PostCustomField.where(name: "polls").find_each do |pcf|
+      polls = ::JSON.parse(pcf.value)
+      polls.each_value do |poll|
+        next if poll.has_key?("voters")
+        poll["voters"] = poll["total_votes"]
+        poll.delete("total_votes")
+      end
+      pcf.value = polls.to_json
+      pcf.save
+    end
+  end
+
+  def down
+    PostCustomField.where(name: "polls").find_each do |pcf|
+      polls = ::JSON.parse(pcf.value)
+      polls.each_value do |poll|
+        next if poll.has_key?("total_votes")
+        poll["total_votes"] = poll["voters"]
+        poll.delete("voters")
+      end
+      pcf.value = polls.to_json
+      pcf.save
+    end
+  end
+
+end
diff --git a/plugins/poll/plugin.rb b/plugins/poll/plugin.rb
index 76f814bef..3155d20b2 100644
--- a/plugins/poll/plugin.rb
+++ b/plugins/poll/plugin.rb
@@ -14,15 +14,6 @@ VOTES_CUSTOM_FIELD ||= "polls-votes".freeze
 
 after_initialize do
 
-  # PERF, avoids N+1 in serializer
-  TopicView.add_post_custom_fields_whitelister do |user|
-    POLLS_CUSTOM_FIELD
-  end
-
-  TopicView.add_post_custom_fields_whitelister do |user|
-    VOTES_CUSTOM_FIELD
-  end
-
   # remove "Vote Now!" & "Show Results" links in emails
   Email::Styles.register_plugin_style do |fragment|
     fragment.css(".poll a.cast-votes, .poll a.toggle-results").each(&:remove)
@@ -66,7 +57,7 @@ after_initialize do
           vote = votes[poll_name] || []
 
           # increment counters only when the user hasn't casted a vote yet
-          poll["total_votes"] += 1 if vote.size == 0
+          poll["voters"] += 1 if vote.size == 0
 
           poll["options"].each do |option|
             option["votes"] -= 1 if vote.include?(option["id"])
@@ -125,7 +116,7 @@ after_initialize do
 
         # extract polls
         parsed.css("div.poll").each do |p|
-          poll = { "options" => [], "total_votes" => 0 }
+          poll = { "options" => [], "voters" => 0 }
 
           # extract attributes
           p.attributes.values.each do |attribute|
@@ -217,9 +208,10 @@ after_initialize do
     # only care when raw has changed!
     return unless self.raw_changed?
 
-    extracted_polls = DiscoursePoll::Poll::extract(self.raw, self.topic_id)
     polls = {}
 
+    extracted_polls = DiscoursePoll::Poll::extract(self.raw, self.topic_id)
+
     extracted_polls.each do |poll|
       # polls should have a unique name
       if polls.has_key?(poll["name"])
@@ -297,7 +289,7 @@ after_initialize do
             next unless previous_polls.has_key?(poll_name)
             next unless polls[poll_name]["options"].size == previous_polls[poll_name]["options"].size
 
-            polls[poll_name]["total_votes"] = previous_polls[poll_name]["total_votes"]
+            polls[poll_name]["voters"] = previous_polls[poll_name]["voters"]
             for o in 0...polls[poll_name]["options"].size
               polls[poll_name]["options"][o]["votes"] = previous_polls[poll_name]["options"][o]["votes"]
             end
diff --git a/plugins/poll/spec/controllers/polls_controller_spec.rb b/plugins/poll/spec/controllers/polls_controller_spec.rb
index ab9081285..54ee2c4d2 100644
--- a/plugins/poll/spec/controllers/polls_controller_spec.rb
+++ b/plugins/poll/spec/controllers/polls_controller_spec.rb
@@ -17,7 +17,7 @@ describe ::DiscoursePoll::PollsController do
       expect(response).to be_success
       json = ::JSON.parse(response.body)
       expect(json["poll"]["name"]).to eq("poll")
-      expect(json["poll"]["total_votes"]).to eq(1)
+      expect(json["poll"]["voters"]).to eq(1)
       expect(json["vote"]).to eq(["5c24fc1df56d764b550ceae1b9319125"])
     end
 
@@ -36,7 +36,7 @@ describe ::DiscoursePoll::PollsController do
       xhr :put, :vote, { post_id: poll.id, poll_name: "poll", options: ["e89dec30bbd9bf50fabf6a05b4324edf"] }
       expect(response).to be_success
       json = ::JSON.parse(response.body)
-      expect(json["poll"]["total_votes"]).to eq(1)
+      expect(json["poll"]["voters"]).to eq(1)
       expect(json["poll"]["options"][0]["votes"]).to eq(0)
       expect(json["poll"]["options"][1]["votes"]).to eq(1)
     end