diff --git a/lib/resources/submissions.js b/lib/resources/submissions.js
index 69fa97821..5b327e08d 100644
--- a/lib/resources/submissions.js
+++ b/lib/resources/submissions.js
@@ -127,7 +127,16 @@ module.exports = (service, endpoint) => {
                   return Promise.all([
                     Submissions.createNew(partial, form, query.deviceID, userAgent),
                     Forms.getBinaryFields(form.def.id)
-                  ]).then(([ saved, binaryFields ]) => SubmissionAttachments.create(saved, form, binaryFields, files));
+                  ])
+                    .then(([ saved, binaryFields ]) => SubmissionAttachments.create(saved, form, binaryFields, files))
+                    .catch((error) => {
+                      // This is only true when submission is soft deleted, if it is hard deleted then there will no error
+                      // and if it is not deleted then `extant` will be not null and this block will not execute.
+                      if (error.isProblem === true && error.problemCode === 409.3) {
+                        throw Problem.user.duplicateSubmission();
+                      }
+                      throw error;
+                    });
                 });
           })
           .then(always(createdMessage({ message: 'full submission upload was successful!' }))))));
diff --git a/lib/util/problem.js b/lib/util/problem.js
index 4ed87ac66..3082bfcdf 100644
--- a/lib/util/problem.js
+++ b/lib/util/problem.js
@@ -221,7 +221,9 @@ const problems = {
 
     entityVersionConflict: problem(409.15, ({ current, provided }) => `Current version of the Entity is '${current}' and you provided '${provided}'. Please correct the version number or pass '?force=true' in the URL to forcefully update the Entity.`),
 
-    datasetNameConflict: problem(409.16, ({ current, provided }) => `A dataset named '${current}' exists and you provided '${provided}' with the same name but different capitalization.`)
+    datasetNameConflict: problem(409.16, ({ current, provided }) => `A dataset named '${current}' exists and you provided '${provided}' with the same name but different capitalization.`),
+
+    duplicateSubmission: problem(409.18, () => `This submission has been deleted. You may not resubmit it.`)
 
   },
   internal: {
diff --git a/test/integration/api/submissions.js b/test/integration/api/submissions.js
index a031bc77a..7021cb5af 100644
--- a/test/integration/api/submissions.js
+++ b/test/integration/api/submissions.js
@@ -572,6 +572,26 @@ describe('api: /submission', () => {
               .then(({ body }) => { body.toString('utf8').should.equal('this is test file one'); })
           ])))));
 
+    it('should reject resubmission of soft-deleted submission', testService(async (service) => {
+      const asAlice = await service.login('alice');
+
+      await asAlice.post('/v1/projects/1/submission')
+        .set('X-OpenRosa-Version', '1.0')
+        .attach('xml_submission_file', Buffer.from(testData.instances.simple.one), { filename: 'data.xml' })
+        .expect(201);
+
+      await asAlice.delete('/v1/projects/1/forms/simple/submissions/one')
+        .expect(200);
+
+      await asAlice.post('/v1/projects/1/submission')
+        .set('X-OpenRosa-Version', '1.0')
+        .attach('xml_submission_file', Buffer.from(testData.instances.simple.one), { filename: 'data.xml' })
+        .expect(409)
+        .then(({ text }) => {
+          text.includes('This submission has been deleted. You may not resubmit it.').should.be.true();
+        });
+    }));
+
     context('versioning', () => {
       it('should reject if the deprecatedId is not known', testService((service) =>
         service.login('alice', (asAlice) =>
@@ -1153,6 +1173,20 @@ describe('api: /forms/:id/submissions', () => {
                 ]);
               })
           ])))));
+
+    it('should reject duplicate submissions', testService(async (service) => {
+      const asAlice = await service.login('alice');
+
+      await asAlice.post('/v1/projects/1/forms/simple/submissions')
+        .send(testData.instances.simple.one)
+        .set('Content-Type', 'text/xml')
+        .expect(200);
+
+      await asAlice.post('/v1/projects/1/forms/simple/submissions')
+        .send(testData.instances.simple.one)
+        .set('Content-Type', 'text/xml')
+        .expect(409);
+    }));
   });
 
   describe('[draft] POST', () => {