diff --git a/public/language/en_GB/error.json b/public/language/en_GB/error.json
index 6d64645c59..8bb83071fc 100644
--- a/public/language/en_GB/error.json
+++ b/public/language/en_GB/error.json
@@ -45,6 +45,7 @@
 	"category-disabled": "Category disabled",
 
 	"topic-locked": "Topic Locked",
+	"post-edit-duration-expired": "You are only allowed to edit posts for %1 seconds after posting",
 
 	"still-uploading": "Please wait for uploads to complete.",
 	"content-too-short": "Please enter a longer post. Posts should contain at least %1 characters.",
diff --git a/src/privileges/posts.js b/src/privileges/posts.js
index 7c304a1a2c..5e012dc9e9 100644
--- a/src/privileges/posts.js
+++ b/src/privileges/posts.js
@@ -4,6 +4,7 @@
 var async = require('async'),
 	winston = require('winston'),
 
+	meta = require('../meta'),
 	posts = require('../posts'),
 	topics = require('../topics'),
 	user = require('../user'),
@@ -108,27 +109,24 @@ module.exports = function(privileges) {
 	};
 
 	privileges.posts.canEdit = function(pid, uid, callback) {
-		helpers.some([
-			function(next) {
-				isPostTopicLocked(pid, function(err, isLocked) {
-					if (err || isLocked) {
-						return next(err, false);
-					}
-
-					helpers.some([
-						function(next) {
-							posts.isOwner(pid, uid, next);
-						},
-						function(next) {
-							helpers.hasEnoughReputationFor(['privileges:manage_content', 'privileges:manage_topic'], uid, next);
-						}
-					], next);
-				});
-			},
-			function(next) {
-				isAdminOrMod(pid, uid, next);
+		async.parallel({
+			isEditable: async.apply(isPostEditable, pid, uid),
+			isAdminOrMod: async.apply(isAdminOrMod, pid, uid)
+		}, function(err, results) {
+			if (err) {
+				return callback(err);
 			}
-		], callback);
+			if (results.isAdminOrMod) {
+				return callback(null, true);
+			}
+			if (results.isEditable.isLocked) {
+				return callback(new Error('[[error:topic-locked]]]'));
+			}
+			if (results.isEditable.isEditExpired) {
+				return callback(new Error('[[error:post-edit-duration-expired, ' + meta.config.postEditDuration + ']]'));
+			}
+			callback(null, results.isEditable.editable);
+		});		
 	};
 
 	privileges.posts.canMove = function(pid, uid, callback) {
@@ -140,6 +138,36 @@ module.exports = function(privileges) {
 		});
 	};
 
+	function isPostEditable(pid, uid, callback) {
+		async.waterfall([
+			function(next) {
+				posts.getPostFields(pid, ['tid', 'timestamp'], next);
+			},
+			function(postData, next) {
+				var postEditDuration = parseInt(meta.config.postEditDuration, 10);
+				if (postEditDuration && Date.now() - parseInt(postData.timestamp, 10) > postEditDuration * 1000) {
+					return callback(null, {isEditExpired: true});
+				}
+				topics.isLocked(postData.tid, next);
+			},
+			function(isLocked, next) {
+				if (isLocked) {
+					return callback(null, {isLocked: true});
+				}
+				helpers.some([
+					function(next) {
+						posts.isOwner(pid, uid, next);
+					},
+					function(next) {
+						helpers.hasEnoughReputationFor(['privileges:manage_content', 'privileges:manage_topic'], uid, next);
+					}
+				], function(err, editable) {
+					next(err, {editable: editable});
+				});
+			}
+		], callback);
+	}
+
 	function isPostTopicLocked(pid, callback) {
 		posts.getPostField(pid, 'tid', function(err, tid) {
 			if (err) {
diff --git a/src/views/admin/settings/post.tpl b/src/views/admin/settings/post.tpl
index 98b99f3973..2ec28c23a1 100644
--- a/src/views/admin/settings/post.tpl
+++ b/src/views/admin/settings/post.tpl
@@ -37,6 +37,10 @@
 				<label>Seconds before new user can post</label>
 				<input type="number" class="form-control" value="10" data-field="initialPostDelay">
 			</div>
+			<div class="form-group">
+				<label>Number of seconds users are allowed to edit posts after posting. (0 disabled)</label>
+				<input type="number" class="form-control" value="0" data-field="postEditDuration">
+			</div>
 			<div class="form-group">
 				<label>Minimum Title Length</label>
 				<input type="number" class="form-control" value="3" data-field="minimumTitleLength">