diff --git a/plug.vim b/plug.vim
index 9ebcf533..2b696209 100644
--- a/plug.vim
+++ b/plug.vim
@@ -109,6 +109,9 @@ let s:TYPE = {
 \ }
 let s:loaded = get(s:, 'loaded', {})
 let s:triggers = get(s:, 'triggers', {})
+let s:need_filetypeplugin_au = 0
+let s:need_filetypeindent_au = 0
+let s:autocmd_queue_for_vimenter = []
 
 function! plug#begin(...)
   if a:0 > 0
@@ -209,6 +212,21 @@ function! plug#end()
   if exists('g:did_load_filetypes')
     filetype off
   endif
+
+  let warn = []
+  if exists('g:did_load_ftplugin')
+    let warn += ['plugin']
+    let s:need_filetypeindent_au = 1
+  endif
+  if exists('g:did_indent_on')
+    let warn += ['indent']
+    let s:need_filetypeplugin_au = 1
+  endif
+  if !empty(warn)
+    redraw
+    call s:warn('echom', printf('[vim-plug] "filetype %s on" should not be used manually with vim-plug, please remove it from your vimrc.', join(warn)))
+  endif
+
   for name in g:plugs_order
     if !has_key(g:plugs, name)
       continue
@@ -281,7 +299,21 @@ function! plug#end()
     if has('syntax') && !exists('g:syntax_on')
       syntax enable
     end
+
+    " NOTE: v:vim_did_enter might not exist with older Vims, and handling it
+    " manually can be used in tests.
+    let s:vim_did_enter = 0
+    function! s:plug_on_vimenter()
+      let s:vim_did_enter = 1
+      for event in s:autocmd_queue_for_vimenter
+        call s:doautocmd(event)
+      endfor
+    endfunction
+    augroup PlugLOD
+      autocmd VimEnter * call s:plug_on_vimenter()
+    augroup END
   else
+    let s:vim_did_enter = 1
     call s:reload_plugins()
   endif
 endfunction
@@ -419,6 +451,12 @@ function! s:reorg_rtp()
 endfunction
 
 function! s:doautocmd(...)
+  if !s:vim_did_enter
+    if index(s:autocmd_queue_for_vimenter, a:000) == -1
+      call add(s:autocmd_queue_for_vimenter, a:000)
+    endif
+    return
+  endif
   if exists('#'.join(a:000, '#'))
     execute 'doautocmd' ((v:version > 703 || has('patch442')) ? '<nomodeline>' : '') join(a:000)
   endif
@@ -429,9 +467,7 @@ function! s:dobufread(names)
     let path = s:rtp(g:plugs[name]).'/**'
     for dir in ['ftdetect', 'ftplugin']
       if len(finddir(dir, path))
-        if exists('#BufRead')
-          doautocmd BufRead
-        endif
+        call s:doautocmd('BufRead')
         return
       endif
     endfor
@@ -502,8 +538,17 @@ function! s:lod_ft(pat, names)
   let syn = 'syntax/'.a:pat.'.vim'
   call s:lod(a:names, ['plugin', 'after/plugin'], syn, 'after/'.syn)
   execute 'autocmd! PlugLOD FileType' a:pat
-  call s:doautocmd('filetypeplugin', 'FileType')
-  call s:doautocmd('filetypeindent', 'FileType')
+
+  " Executing this is only necessary if "filetype plugin indent on" was used
+  " before plug#end, and can be skipped when Vim has not entered always.
+  if s:vim_did_enter
+    if s:need_filetypeplugin_au
+      call s:doautocmd('filetypeplugin', 'FileType')
+    endif
+    if s:need_filetypeindent_au
+      call s:doautocmd('filetypeindent', 'FileType')
+    endif
+  endif
 endfunction
 
 function! s:lod_cmd(cmd, bang, l1, l2, args, names)
diff --git a/test/regressions.vader b/test/regressions.vader
index dd2a6a2e..aa0a3a06 100644
--- a/test/regressions.vader
+++ b/test/regressions.vader
@@ -5,6 +5,10 @@ Execute (#112 On-demand loading should not suppress messages from ftplugin):
   Plug '$PLUG_FIXTURES/ftplugin-msg', { 'for': 'c' }
   call plug#end()
 
+  " Trigger VimEnter (simulate Vim being started), so that s:lod handles
+  " filetypeindent/filetypeplugin."
+  doautocmd VimEnter
+
   redir => out
   tabnew a.c
   redir END
diff --git a/test/workflow.vader b/test/workflow.vader
index b0a43a17..7f0c13d4 100644
--- a/test/workflow.vader
+++ b/test/workflow.vader
@@ -1117,7 +1117,7 @@ Execute (Filetype-based on-demand loading):
   AssertEqual ['xxx/ftdetect', 'xxx/after/ftdetect'], g:xxx
 
   setf xxx
-  AssertEqual ['xxx/ftdetect', 'xxx/after/ftdetect', 'xxx/plugin', 'xxx/after/plugin', 'xxx/syntax', 'xxx/after/syntax', 'xxx/ftplugin', 'xxx/after/ftplugin', 'xxx/indent', 'xxx/after/indent'], g:xxx
+  AssertEqual ['xxx/ftdetect', 'xxx/after/ftdetect', 'xxx/plugin', 'xxx/after/plugin', 'xxx/syntax', 'xxx/after/syntax'], g:xxx
 
   " syntax/xxx.vim and after/syntax/xxx.vim should not be loaded (#410)
   setf yyy