diff --git a/java/src/com/android/inputmethod/event/CombinerChain.java b/java/src/com/android/inputmethod/event/CombinerChain.java
index 5ca9842c1e1e6aeecdf343b8d6885ded62ac731b..8b59dc52a870b47cf1f2176b08d7eebfec9957b7 100644
--- a/java/src/com/android/inputmethod/event/CombinerChain.java
+++ b/java/src/com/android/inputmethod/event/CombinerChain.java
@@ -17,7 +17,9 @@
 package com.android.inputmethod.event;
 
 import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
 
+import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.utils.CollectionUtils;
 
 import java.util.ArrayList;
@@ -84,7 +86,19 @@ public class CombinerChain {
             }
         }
         if (null != event) {
-            mCombinedText.append(event.getTextToCommit());
+            // TODO: figure out the generic way of doing this
+            if (Constants.CODE_DELETE == event.mKeyCode) {
+                final int length = mCombinedText.length();
+                if (length > 0) {
+                    final int lastCodePoint = mCombinedText.codePointBefore(length);
+                    mCombinedText.delete(length - Character.charCount(lastCodePoint), length);
+                }
+            } else {
+                final CharSequence textToCommit = event.getTextToCommit();
+                if (!TextUtils.isEmpty(textToCommit)) {
+                    mCombinedText.append(textToCommit);
+                }
+            }
         }
         mStateFeedback.clear();
         for (int i = mCombiners.size() - 1; i >= 0; --i) {
diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java
index 2bfe0732d7c635e59294891d11d5209b8d42ad96..646590948fa89e760c84ebedc452997b2fdb775b 100644
--- a/java/src/com/android/inputmethod/event/Event.java
+++ b/java/src/com/android/inputmethod/event/Event.java
@@ -229,9 +229,9 @@ public class Event {
         switch (mType) {
         case EVENT_MODE_KEY:
         case EVENT_NOT_HANDLED:
+        case EVENT_TOGGLE:
             return "";
         case EVENT_INPUT_KEYPRESS:
-        case EVENT_TOGGLE:
             return StringUtils.newSingleCodePointString(mCodePoint);
         case EVENT_GESTURE:
         case EVENT_SOFTWARE_GENERATED_STRING:
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index ba64028caf6724743ea48751f14d226e2fdb2b39..82dbe3c438f4ac2c6801ec9feea2f79f2100e1fc 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.latin;
 
 import android.text.TextUtils;
 
+import com.android.inputmethod.event.Event;
 import com.android.inputmethod.keyboard.ProximityInfo;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.define.ProductionFlag;
@@ -121,7 +122,11 @@ public final class Suggest {
         if (trailingSingleQuotesCount > 0) {
             wordComposerForLookup = new WordComposer(wordComposer);
             for (int i = trailingSingleQuotesCount - 1; i >= 0; --i) {
-                wordComposerForLookup.deleteLast();
+                // TODO: do not create a fake event for this. Ideally the word composer should know
+                // how to give out the word without trailing quotes and we can remove this entirely
+                wordComposerForLookup.deleteLast(Event.createSoftwareKeypressEvent(
+                        Event.NOT_A_CODE_POINT, Constants.CODE_DELETE,
+                        Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE));
             }
         } else {
             wordComposerForLookup = wordComposer;
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index a60ca3d414c88c51bd3b054f7b676e533424ee11..a955f375ba0170120645f8da4c7b985f8b169fb2 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -314,29 +314,14 @@ public final class WordComposer {
     }
 
     /**
-     * Delete the last keystroke as a result of hitting backspace.
+     * Delete the last composing unit as a result of hitting backspace.
      */
-    public void deleteLast() {
-        final int size = size();
-        if (size > 0) {
-            // Note: mTypedWord.length() and mCodes.length differ when there are surrogate pairs
-            final int stringBuilderLength = mTypedWord.length();
-            if (stringBuilderLength < size) {
-                throw new RuntimeException(
-                        "In WordComposer: mCodes and mTypedWords have non-matching lengths");
-            }
-            final int lastChar = mTypedWord.codePointBefore(stringBuilderLength);
-            // TODO: with events and composition, this is absolutely not necessarily true.
-            mEvents.remove(mEvents.size() - 1);
-            if (Character.isSupplementaryCodePoint(lastChar)) {
-                mTypedWord.delete(stringBuilderLength - 2, stringBuilderLength);
-            } else {
-                mTypedWord.deleteCharAt(stringBuilderLength - 1);
-            }
-            if (Character.isUpperCase(lastChar)) mCapsCount--;
-            if (Character.isDigit(lastChar)) mDigitsCount--;
-            refreshSize();
-        }
+    public void deleteLast(final Event event) {
+        mCombinerChain.processEvent(mEvents, event);
+        mTypedWord.replace(0, mTypedWord.length(),
+                mCombinerChain.getComposingWordWithCombiningFeedback().toString());
+        mEvents.add(event);
+        refreshSize();
         // We may have deleted the last one.
         if (0 == size()) {
             mIsFirstCharCapitalized = false;
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 36b30eabec2020d70496e39e0d09660e55049326..fdba0d1f3b4317159b20280e37181057f0bf1c6d 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -922,7 +922,7 @@ public final class InputLogic {
                 mWordComposer.reset();
                 mWordComposer.setRejectedBatchModeSuggestion(rejectedSuggestion);
             } else {
-                mWordComposer.deleteLast();
+                mWordComposer.deleteLast(inputTransaction.mEvent);
             }
             mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
             handler.postUpdateSuggestionStrip();
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
index ab6245635d49258d4db95f6b377e730f25e0a7c2..d4e6ad87ae92e29c480b08453ec883882ef9fb43 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -454,4 +454,24 @@ public class InputLogicTests extends InputTestsBase {
         assertEquals("predictions after recorrection", "Obama",
                 suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null);
     }
+
+    public void testComposingMultipleBackspace() {
+        final String WORD_TO_TYPE = "radklro";
+        final int TIMES_TO_TYPE = 3;
+        final int TIMES_TO_BACKSPACE = 8;
+        type(WORD_TO_TYPE);
+        type(Constants.CODE_DELETE);
+        type(Constants.CODE_DELETE);
+        type(Constants.CODE_DELETE);
+        type(WORD_TO_TYPE);
+        type(Constants.CODE_DELETE);
+        type(Constants.CODE_DELETE);
+        type(WORD_TO_TYPE);
+        type(Constants.CODE_DELETE);
+        type(Constants.CODE_DELETE);
+        type(Constants.CODE_DELETE);
+        assertEquals("composing with multiple backspace",
+                WORD_TO_TYPE.length() * TIMES_TO_TYPE - TIMES_TO_BACKSPACE,
+                mEditText.getText().length());
+    }
 }