diff --git a/book/src/configuration.md b/book/src/configuration.md
index d47f95d9..7d6ff28f 100644
--- a/book/src/configuration.md
+++ b/book/src/configuration.md
@@ -21,6 +21,7 @@ To override global configuration parameters, create a `config.toml` file located
 | `auto-pairs` | Enable automatic insertion of pairs to parenthese, brackets, etc. | `true` |
 | `auto-completion` | Enable automatic pop up of auto-completion. | `true` |
 | `idle-timeout` | Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. | `400` |
+| `completion-trigger-len` | The min-length of word under cursor to trigger autocompletion | `2` |
 
 ## LSP
 
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index 0e7d0e55..a7281ecf 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -235,7 +235,7 @@ impl Application {
     }
 
     pub fn handle_idle_timeout(&mut self) {
-        use crate::commands::{completion, Context};
+        use crate::commands::{insert::idle_completion, Context};
         use helix_view::document::Mode;
 
         if doc_mut!(self.editor).mode != Mode::Insert || !self.config.editor.auto_completion {
@@ -262,7 +262,7 @@ impl Application {
             callback: None,
             on_next_key_callback: None,
         };
-        completion(&mut cx);
+        idle_completion(&mut cx);
         self.render();
     }
 
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 95c46a4e..2811f293 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -3308,7 +3308,26 @@ pub mod insert {
     pub type Hook = fn(&Rope, &Selection, char) -> Option<Transaction>;
     pub type PostHook = fn(&mut Context, char);
 
-    fn completion(cx: &mut Context, ch: char) {
+    // It trigger completion when idle timer reaches deadline
+    // Only trigger completion if the word under cursor is longer than n characters
+    pub fn idle_completion(cx: &mut Context) {
+        let (view, doc) = current!(cx.editor);
+        let text = doc.text().slice(..);
+        let cursor = doc.selection(view.id).primary().cursor(text);
+
+        use helix_core::chars::char_is_word;
+        let mut iter = text.chars_at(cursor);
+        iter.reverse();
+        for _ in 0..cx.editor.config.completion_trigger_len {
+            match iter.next() {
+                Some(c) if char_is_word(c) => {}
+                _ => return,
+            }
+        }
+        super::completion(cx);
+    }
+
+    fn language_server_completion(cx: &mut Context, ch: char) {
         // if ch matches completion char, trigger completion
         let doc = doc_mut!(cx.editor);
         let language_server = match doc.language_server() {
@@ -3318,19 +3337,14 @@ pub mod insert {
 
         let capabilities = language_server.capabilities();
 
-        if let lsp::ServerCapabilities {
-            completion_provider:
-                Some(lsp::CompletionOptions {
-                    trigger_characters: Some(triggers),
-                    ..
-                }),
+        if let Some(lsp::CompletionOptions {
+            trigger_characters: Some(triggers),
             ..
-        } = capabilities
+        }) = &capabilities.completion_provider
         {
             // TODO: what if trigger is multiple chars long
-            let is_trigger = triggers.iter().any(|trigger| trigger.contains(ch));
-
-            if is_trigger {
+            if triggers.iter().any(|trigger| trigger.contains(ch)) {
+                cx.editor.clear_idle_timer();
                 super::completion(cx);
             }
         }
@@ -3412,7 +3426,8 @@ pub mod insert {
         // TODO: need a post insert hook too for certain triggers (autocomplete, signature help, etc)
         // this could also generically look at Transaction, but it's a bit annoying to look at
         // Operation instead of Change.
-        for hook in &[completion, signature_help] {
+        for hook in &[language_server_completion, signature_help] {
+            // for hook in &[signature_help] {
             hook(cx, c);
         }
     }
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index 90e3bf47..52fca6d2 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -58,6 +58,7 @@ pub struct Config {
     /// Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. Defaults to 400ms.
     #[serde(skip_serializing, deserialize_with = "deserialize_duration_millis")]
     pub idle_timeout: Duration,
+    pub completion_trigger_len: u8,
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
@@ -87,6 +88,7 @@ impl Default for Config {
             auto_pairs: true,
             auto_completion: true,
             idle_timeout: Duration::from_millis(400),
+            completion_trigger_len: 2,
         }
     }
 }