It would be nice if group creation can be fully in separate function instead of just the batch execution:
```python

def check_groups(cur_groups, max_groups):
    if cur_groups[0]['count'] >= max_groups:
        log.msg('client has reached maxGroups limit')
        raise OverLimitError(tenant_id, max_groups)

d.addCallback(check_groups, max_groups)

def _create_group(_):
    log.msg("Creating scaling group")
    queries = [_cql_create_group.format(cf=self.group_table)]
    data = {
        "tenantId": tenant_id,
        "groupId": scaling_group_id,
        "group_config": serialize_json_data(config, 1),
        "launch_config": serialize_json_data(launch, 1),
        "active": '{}',
        "pending": '{}',
        "created_at": datetime.utcnow(),
        "policyTouched": '{}',
        "paused": False
    }
    scaling_group_state = GroupState(
        tenant_id,
        scaling_group_id,
        config['name'],
        {},
        {},
        data['created_at'],
        {},
        data['paused']
    )
    outpolicies = _build_policies(policies, self.policies_table,
                                  self.event_table, queries, data)
    b = Batch(queries, data,
              consistency=get_consistency_level('create', 'group'))
    bd = b.execute(self.connection)
    bd.addCallback(lambda _: {
        'groupConfiguration': config,
        'launchConfiguration': launch,
        'scalingPolicies': outpolicies,
        'id': scaling_group_id,
        'state': scaling_group_state
    })
    return bd

 return d.addCallback(_create_group)
```
This way it becomes clear that first group count is checked and then group is created.