diff --git a/java-overridable/src/com/android/inputmethod/latin/accounts/LoginAccountUtils.java b/java-overridable/src/com/android/inputmethod/latin/accounts/LoginAccountUtils.java
index 2dc001c83ee828eef226bc7a88da9717f26cffaf..70f152acbd2b682617bac8e30b45d58ad1976608 100644
--- a/java-overridable/src/com/android/inputmethod/latin/accounts/LoginAccountUtils.java
+++ b/java-overridable/src/com/android/inputmethod/latin/accounts/LoginAccountUtils.java
@@ -16,9 +16,11 @@
 
 package com.android.inputmethod.latin.accounts;
 
+import android.accounts.Account;
 import android.content.Context;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 /**
  * Utility class for retrieving accounts that may be used for login.
@@ -37,4 +39,9 @@ public class LoginAccountUtils {
     public static String[] getAccountsForLogin(final Context context) {
         return new String[0];
     }
+
+    @Nullable
+    public static Account getCurrentAccount(final Context context) {
+        return null;
+    }
 }
diff --git a/java-overridable/src/com/android/inputmethod/latin/define/ProductionFlags.java b/java-overridable/src/com/android/inputmethod/latin/define/ProductionFlags.java
index 9d7258de7cc5a91d364170c68ee9621cadf22ae7..53c746226c3cb46c57551a272c42931a9cc2f3f5 100644
--- a/java-overridable/src/com/android/inputmethod/latin/define/ProductionFlags.java
+++ b/java-overridable/src/com/android/inputmethod/latin/define/ProductionFlags.java
@@ -50,4 +50,9 @@ public final class ProductionFlags {
      * When {@code false}, account sign-in in keyboard is not yet ready to be enabled.
      */
     public static final boolean ENABLE_ACCOUNT_SIGN_IN = false;
+
+    /**
+     * When {@code true}, personal dictionary sync feature is ready to be enabled.
+     */
+    public static final boolean ENABLE_PERSONAL_DICTIONARY_SYNC = false;
 }
diff --git a/java-overridable/src/com/android/inputmethod/latin/sync/BeanstalkManager.java b/java-overridable/src/com/android/inputmethod/latin/sync/BeanstalkManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..2242d92443e8bf53ddfdbb3346f200ca08d545b5
--- /dev/null
+++ b/java-overridable/src/com/android/inputmethod/latin/sync/BeanstalkManager.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin.sync;
+
+import android.content.Context;
+
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.GuardedBy;
+
+public class BeanstalkManager {
+    private static final Object sLock = new Object();
+
+    @GuardedBy("sLock")
+    private static BeanstalkManager sInstance;
+
+    /**
+     * @return the singleton instance of {@link BeanstalkManager}.
+     */
+    @Nonnull
+    public static BeanstalkManager getInstance(Context context) {
+        synchronized(sLock) {
+            if (sInstance == null) {
+                sInstance = new BeanstalkManager(context.getApplicationContext());
+            }
+        }
+        return sInstance;
+    }
+
+    private BeanstalkManager(final Context context) {
+        // Intentional private constructor for singleton.
+    }
+
+    public void onCreate() {
+    }
+
+    public void requestSync() {
+    }
+
+    public void onDestroy() {
+    }
+}
\ No newline at end of file
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 76da5ce3de58637ce3a60a7fc7dcbc75df6bba62..6aea637c5ec38f71d8929c28ba4624c3b5b00e64 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -56,6 +56,10 @@
     <!--  Option for enabling or disabling the split keyboard layout. [CHAR LIMIT=65]-->
     <string name="enable_split_keyboard">Enable split keyboard</string>
 
+    <string name="sync_now_title" translatable="false">Sync Now</string>
+    <string name="sync_now_summary" translatable="false">Sync your personal dictionary</string>
+    <string name="sync_now_summary_disabled_signed_out" translatable="false">Select an account to enable sync</string>
+
     <!-- Option name for including other IMEs in the language switch list [CHAR LIMIT=30] -->
     <string name="include_other_imes_in_language_switch_list">Switch to other input methods</string>
     <!-- Option summary for including other IMEs in the language switch list [CHAR LIMIT=65] -->
diff --git a/java/res/xml/prefs_screen_accounts.xml b/java/res/xml/prefs_screen_accounts.xml
index b5d526a3aa5de5c9318d10ee32abbb63ef1486c8..003a37ff768bad7e5e9d5cb2bfb352ffdcef76df 100644
--- a/java/res/xml/prefs_screen_accounts.xml
+++ b/java/res/xml/prefs_screen_accounts.xml
@@ -34,4 +34,9 @@
         android:summary="@string/enable_metrics_logging_summary"
         android:defaultValue="true"
         android:persistent="true" />
+
+    <!-- This preference (acts like a button) enables the user to initiate an one time sync. -->
+    <Preference android:key="pref_beanstalk"
+        android:persistent="false"
+        android:title="@string/sync_now_title" />
 </PreferenceScreen>
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index a6be75943527a792c5e296b0577d5c59b306d31f..6b7007e5e6c6183f7a56f64fa2d1d75ad50b7bc6 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -84,6 +84,7 @@ import com.android.inputmethod.latin.settings.SettingsActivity;
 import com.android.inputmethod.latin.settings.SettingsValues;
 import com.android.inputmethod.latin.suggestions.SuggestionStripView;
 import com.android.inputmethod.latin.suggestions.SuggestionStripViewAccessor;
+import com.android.inputmethod.latin.sync.BeanstalkManager;
 import com.android.inputmethod.latin.touchinputconsumer.GestureConsumer;
 import com.android.inputmethod.latin.utils.ApplicationUtils;
 import com.android.inputmethod.latin.utils.CapsModeUtils;
@@ -537,6 +538,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         AudioAndHapticFeedbackManager.init(this);
         AccessibilityUtils.init(this);
         mStatsUtilsManager.onCreate(this /* context */);
+        BeanstalkManager.getInstance(this /* context */).onCreate();
         super.onCreate();
 
         mHandler.onCreate();
@@ -686,6 +688,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         unregisterReceiver(mDictionaryPackInstallReceiver);
         unregisterReceiver(mDictionaryDumpBroadcastReceiver);
         mStatsUtilsManager.onDestroy();
+        BeanstalkManager.getInstance(this /* context */).onDestroy();
         super.onDestroy();
     }
 
diff --git a/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java
index ffb0ad7bf8d6741daae503b96501534651b7fc33..a02cb5539d5b6f4df83c7cd6e75086642bbd1cab 100644
--- a/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java
@@ -32,6 +32,7 @@ import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.SubtypeSwitcher;
 import com.android.inputmethod.latin.accounts.LoginAccountUtils;
 import com.android.inputmethod.latin.define.ProductionFlags;
+import com.android.inputmethod.latin.sync.BeanstalkManager;
 
 import javax.annotation.Nullable;
 
@@ -42,14 +43,17 @@ import javax.annotation.Nullable;
  * <li> Account selection/management for IME
  * <li> TODO: Sync preferences
  * <li> TODO: Privacy preferences
+ * <li> Sync now
  */
 public final class AccountsSettingsFragment extends SubScreenFragment {
     static final String PREF_ACCCOUNT_SWITCHER = "account_switcher";
+    static final String PREF_SYNC_NOW = "pref_beanstalk";
 
     private final DialogInterface.OnClickListener mAccountSelectedListener =
             new AccountSelectedListener();
     private final DialogInterface.OnClickListener mAccountSignedOutListener =
             new AccountSignedOutListener();
+    private final Preference.OnPreferenceClickListener mSyncNowListener = new SyncNowListener();
 
     @Override
     public void onCreate(final Bundle icicle) {
@@ -75,21 +79,39 @@ public final class AccountsSettingsFragment extends SubScreenFragment {
         } else {
             removePreference(Settings.PREF_ENABLE_METRICS_LOGGING);
         }
+
+        if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
+            removePreference(PREF_SYNC_NOW);
+        } else {
+            final Preference syncNowPreference = findPreference(PREF_SYNC_NOW);
+            if (syncNowPreference != null) {
+                syncNowPreference.setOnPreferenceClickListener(mSyncNowListener);
+            }
+        }
     }
 
     @Override
     public void onResume() {
         super.onResume();
-        refreshAccountSelection();
+        refreshUi();
     }
 
     @Override
     public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
         // TODO: Look at the preference that changed before refreshing the view.
+        refreshUi();
+    }
+
+    private void refreshUi() {
         refreshAccountSelection();
+        refreshSyncNow();
     }
 
     private void refreshAccountSelection() {
+        if (!ProductionFlags.ENABLE_ACCOUNT_SIGN_IN) {
+            return;
+        }
+
         final String currentAccount = getCurrentlySelectedAccount();
         final Preference accountSwitcher = findPreference(PREF_ACCCOUNT_SWITCHER);
         if (currentAccount == null) {
@@ -119,6 +141,29 @@ public final class AccountsSettingsFragment extends SubScreenFragment {
         // depend on an account.
     }
 
+    /**
+     * Refreshes the "Sync Now" feature
+     */
+    private void refreshSyncNow() {
+        if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
+            return;
+        }
+
+        final Preference syncNowPreference = findPreference(PREF_SYNC_NOW);
+        if (syncNowPreference == null) {
+            return;
+        }
+
+        final String currentAccount = getCurrentlySelectedAccount();
+        if (currentAccount == null) {
+            syncNowPreference.setEnabled(false);
+            syncNowPreference.setSummary(R.string.sync_now_summary);
+        } else {
+            syncNowPreference.setEnabled(true);
+            syncNowPreference.setSummary(R.string.sync_now_summary_disabled_signed_out);
+        }
+    }
+
     @Nullable
     private String getCurrentlySelectedAccount() {
         return getSharedPreferences().getString(Settings.PREF_ACCOUNT_NAME, null);
@@ -190,4 +235,15 @@ public final class AccountsSettingsFragment extends SubScreenFragment {
                     .apply();
         }
     }
+
+    /**
+     * Listener that initates the process of sync in the background.
+     */
+    class SyncNowListener implements Preference.OnPreferenceClickListener {
+        @Override
+        public boolean onPreferenceClick(final Preference preference) {
+            BeanstalkManager.getInstance(getActivity() /* context */).requestSync();
+            return true;
+        }
+    }
 }