[L] means "last rule of this pass". A virtual host has one pass; in .htaccess, a rewrite ends in an internal redirect that runs the request again, .htaccess files and all, on the new URL. [END] also blocks every later per-directory pass. The difference shows when a rule's output matches its own pattern:
RewriteEngine On
RewriteRule ^(.+)$ app/$1 [L]
# second run: the same file with [END] in place of [L]$ curl -s -o /dev/null -w '%{http_code}\n' localhost:8105/hello.txt # with [L]
500
$ curl -s localhost:8105/hello.txt # with [END]
hello from app/With L, the trace shows 'hello.txt' -> 'app/hello.txt', then under redir#1 the same rule turning that into app/app/hello.txt, and so on until LimitInternalRecursion (default 10) ends it with AH00124: Request exceeded the limit of 10 internal redirects. With END the trace stops at internal redirect with /app/hello.txt: pass two runs, but mod_rewrite sits it out, rules in app/.htaccess included. Use END when a rule's output is final, as in most front controllers, and L when a deeper .htaccess must still see the result.