AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,100 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example" published by Apress, and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible import_tasks vs include_tasks: Key Differences (2026 Guide)

By Luca Berton · Published 2024-01-01 · Category: installation

Complete guide to Ansible import_tasks vs include_tasks. Understand static vs dynamic task loading, when to use each, performance differences, and migration tips with practical examples.

Ansible provides two ways to load external task files: import_tasks (static) and include_tasks (dynamic). They look similar but behave very differently at parse time vs runtime. Choosing the wrong one causes subtle bugs with tags, handlers, and conditionals.

Quick Comparison

Key Differences

| Feature | import_tasks (static) | include_tasks (dynamic) | |---------|------------------------|--------------------------| | When loaded | Playbook parse time | Runtime (when task is reached) | | Tags | Applied to all imported tasks | Only on the include task itself | | when condition | Applied to each imported task | Evaluated once before loading | | Handlers | Can notify imported handlers | Cannot notify included handlers | | Loops | ❌ Cannot use with loop | ✅ Can use with loop | | Variables | Cannot use task-level vars in filename | Can use runtime variables in filename | | --list-tasks | Shows imported tasks | Shows only the include task | | --list-tags | Shows tags from imports | Does not show include tags | | Error detection | Syntax errors caught early | Syntax errors caught at runtime |

import_tasks (Static)

Tasks are inserted into the play at parse time, as if you copied them directly into the playbook.

Basic Usage

Tags with import_tasks

Tags cascade to ALL imported tasks:

when with import_tasks

The when condition is applied to each imported task individually:

❌ Cannot Use Loops

include_tasks (Dynamic)

Tasks are loaded at runtime when the include task is reached.

Basic Usage

Dynamic Filenames

Loops with include_tasks

Tags with include_tasks

Tags apply only to the include task itself, NOT to the tasks inside:

To make tags work with includes, add tags inside the included file:

Or use apply:

When to Use Each

Use import_tasks When: • You need tags to work across the included file • You need handlers defined in the imported file • The filename is static (known at parse time) • You want --list-tasks and --list-tags to show everything • You want early error detection (syntax errors caught before execution)

Use include_tasks When: • The filename is dynamic (uses variables or facts) • You need to run includes in a loop • You want conditional loading (load different files based on conditions) • The included file might not exist (use ignore_errors) • You want tasks to load only when needed (performance)

Roles: import_role vs include_role

The same static/dynamic distinction applies to roles:

import_playbook

For including entire playbooks (only works at the play level, not inside tasks):

> Note: There is no include_playbook. Playbook inclusion is always static.

Common Patterns

OS-Specific Task Loading

Role Structure

Common Mistakes

Tags Not Working with include_tasks

Variable Filename with import_tasks

FAQ

What is the difference between import_tasks and include_tasks?

import_tasks is static — tasks are loaded at playbook parse time and behave as if written directly in the playbook. include_tasks is dynamic — tasks are loaded at runtime when the task is reached. This affects how tags, conditions, and loops work.

Can I use loops with import_tasks?

No, import_tasks does not support loops. Use include_tasks when you need to loop over a task file multiple times.

Why don't my tags work with include_tasks?

Tags on include_tasks only apply to the include task itself, not to the tasks inside the file. Use import_tasks for tag-based filtering, or add apply: with tags to pass them through to included tasks.

Which is better for performance?

include_tasks can be slightly better for large playbooks because tasks are only loaded when needed. import_tasks loads everything upfront. In practice, the difference is negligible for most playbooks.

Should I use import_tasks or include_tasks by default?

Use import_tasks as the default for static, predictable task loading. Switch to include_tasks when you need dynamic filenames, loops, or conditional file loading. If you use tags extensively, prefer import_tasks.

Conclusionimport_tasks — Static, parsed at load time. Tags and when cascade. No loops. Best for predictable structure. • include_tasks — Dynamic, loaded at runtime. Supports loops and variable filenames. Tags need special handling. • Rule of thumb: Use import_tasks unless you need dynamic behavior.

Related ArticlesAnsible Roles: Create Reusable AutomationAnsible Handlers: Trigger Actions on ChangeAnsible Playbook Examples: Complete GuideAnsible Collections: Install, Use & Create

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home