unable to save register value even if the play is skipped!
register will always populate your registered var even when the task is skipped, e.g. you will end up with something like the following:

"kafkaip": {
    "changed": false,
    "skip_reason": "Conditional result was False",
    "skipped": true
}


Since only the commands differ depending on your env, I would store the command in a variable and then execute it, something like the following.

- name: "Set command for env &lt;&gt; QA"
  set_fact:
    get_ip_command: &gt;-
      aws cloudformation describe-stacks
      --stack-name "{{ stack_kafka }}"
      --query "Stacks[*].Outputs[?OutputKey=='KafkaLink'].OutputValue"
  when:
    - stack_kafka is defined
    - ( deployment_env != "QA" )

- name: "Set command for env = QA"
  set_fact:
    get_ip_command: &gt;-
      aws ec2 describe-instances
      --filter "Name=tag:StackName,Values=KafkaCluster"
      --query 'Reservations[].Instances[].PrivateIpAddress'
      --output text
  when:
    - stack_kafka is defined
    - ( deployment_env == "QA" )

- name: Get the Kafka InstancesPrivateIps
  shell: "{{ get_ip_command }}"
  register: kafkaip
  when: stack_kafka is defined

- name: Register kafka_host
  set_fact:
    kafka_host: "{{ kafkaip.stdout }}"
  when: stack_kafka is defined




Note1: there is an output redirection in your QA command which will prevent capturing the output as you wish, I left it out in my example.
Note2: I used set_fact to create the command variable but you can put that in your vars or your inventory to have a leaner playbook.