How to make fake hosts and keep variable scopes apart on the same 'real' hosts

For example if your inventory contains a set of app servers and you want to deploy 20 apps to them all with a variable config: <unique value>

It is kind of non-intuitive but ansible's variables are bound to hostnames and not to groups, so having

[app1]
localhost
[app1:vars]
config=1

[app2]
localhost
[app2:vars]
config=2

If you run

ansible -i <thefileabove> -c local app1 -m debug -a 'var=config'

It will dump

localhost | SUCCESS => {
    "config": 2
}

Regardless of how hard you try to make it 1 :]

If you change your inventory to this however

[app1]
app1host ansible_host=localhost
[app1:vars]
config=1

[app2]
app2host ansible_host=localhost
[app2:vars]
config=2

you'll get the correct behaviour

app1host | SUCCESS => {
    "config": 1
}

Another way to do this is to use add_host in the begining of your playbook to populate an empty group

so with empty groups

[real_servers]
localhost

[app1]
[app1:vars]
config=1

[app2]
[app2:vars]
config=2

You can do this (you can use include to pull in that first play)

- hosts: localhost
  connection: local
  gather_facts: false
  tasks:
    - name: doofo
      add_host:
        name: "{{item.0}}{{item.1}}"
        ansible_host: "{{item.1}}"
        group: "{{item.0}}"
        connection: local
      with_nested:
        - [ app1, app2 ]
        - "{{groups['real_servers']}}"
- hosts: app1 app2
  gather_facts: false
  tasks:
    - debug: var=config

and it will debug like this

ok: [app1localhost] => {
    "config": 1
}
ok: [app2localhost] => {
    "config": 2
}