diff --git a/netbox_awx_plugin/models.py b/netbox_awx_plugin/models.py
index 82567ab52adb6e0dfb4d78dfc45275fd1f26228b..59ea0b65bac3e5d10b2d299b84b4f7889e774da4 100644
--- a/netbox_awx_plugin/models.py
+++ b/netbox_awx_plugin/models.py
@@ -57,6 +57,32 @@ class AWXInventory(NetBoxModel):
         else:
             return None
 
+    def get_all_hosts(self):
+        """
+        Retrieves all hosts from the AWX inventory.
+        """
+        hosts = {}
+        page = 1
+        while True:
+            params = {"page": page}
+            r = requests.get(
+                url=urljoin(
+                    self.awx.url,
+                    f"/api/v2/inventories/{self.inventory_id}/hosts/",
+                ),
+                params=params,
+                headers=self.awx.get_headers(),
+                verify=False,
+            )
+            r.raise_for_status()
+            data = r.json()
+            for host in data["results"]:
+                hosts[host["name"]] = host
+            if not data.get("next"):
+                break
+            page += 1
+        return hosts
+
     def create_host(self, data):
         logger.info("Creating host with: {}".format(data))
         r = requests.post(
@@ -65,7 +91,14 @@ class AWXInventory(NetBoxModel):
             json=data,
             verify=False,
         )
-        r.raise_for_status()
+        if r.status_code == 201:
+            return r.json()  # Return the created host object
+        else:
+            logger.error(
+                f"Failed to create host {data['name']}, Response: "
+                f"{r.text if r else 'No response'}"
+            )
+            return None
 
     def update_host(self, host_id, data):
         logger.info("Updating host with: {}".format(data))
@@ -79,12 +112,17 @@ class AWXInventory(NetBoxModel):
 
     def delete_host(self, hostname):
         host = self.get_host(hostname)
-        r = requests.delete(
-            url=urljoin(self.awx.url, "/api/v2/hosts/{}/".format(host["id"])),
-            headers=self.awx.get_headers(),
-            verify=False,
-        )
-        r.raise_for_status()
+        if host:
+            r = requests.delete(
+                url=urljoin(
+                    self.awx.url, "/api/v2/hosts/{}/".format(host["id"])
+                ),
+                headers=self.awx.get_headers(),
+                verify=False,
+            )
+            r.raise_for_status()
+        else:
+            logger.warning(f"Host {hostname} not found for deletion.")
 
     def get_group(self, name):
         params = {"name": name}
@@ -97,6 +135,32 @@ class AWXInventory(NetBoxModel):
         r.raise_for_status()
         return r.json()["results"][0] if len(r.json()["results"]) > 0 else None
 
+    def get_all_groups(self):
+        """
+        Retrieves all groups from the AWX inventory.
+        """
+        groups = {}
+        page = 1
+        while True:
+            params = {"page": page}
+            r = requests.get(
+                url=urljoin(
+                    self.awx.url,
+                    f"/api/v2/inventories/{self.inventory_id}/groups/",
+                ),
+                params=params,
+                headers=self.awx.get_headers(),
+                verify=False,
+            )
+            r.raise_for_status()
+            data = r.json()
+            for group in data["results"]:
+                groups[group["name"]] = group
+            if not data.get("next"):
+                break
+            page += 1
+        return groups
+
     def update_group(self, name, data):
         logger.info("Updating group {} with: {}".format(name, data))
         group = self.get_group(name)
@@ -116,18 +180,27 @@ class AWXInventory(NetBoxModel):
             json=data,
             verify=False,
         )
-        r.raise_for_status()
+        if r.status_code == 201:
+            return r.json()  # Return the created group object
+        else:
+            logger.error(
+                f"Failed to create group {data['name']}, Response: "
+                f"{r.text if r else 'No response'}"
+            )
+            return None
 
     def delete_group(self, name):
         logger.info("Deleting group {}".format(name))
         group = self.get_group(name)
-        if not group is None:
+        if group is not None:
             r = requests.delete(
                 url=urljoin(self.awx.url, "/api/v2/groups/{}/".format(group["id"])),
                 headers=self.awx.get_headers(),
                 verify=False,
             )
             r.raise_for_status()
+        else:
+            logger.warning(f"Group {name} not found for deletion.")
 
     def associate_host_group(self, host_id, group_id):
         logger.info("Associating host {} to group {}".format(host_id, group_id))
diff --git a/netbox_awx_plugin/synchronization.py b/netbox_awx_plugin/synchronization.py
index 2e727b1692131b45ffd1da8ef579e28fbc170cec..7cf1ee280abca4918ebd4c0307c3fd911384254b 100644
--- a/netbox_awx_plugin/synchronization.py
+++ b/netbox_awx_plugin/synchronization.py
@@ -4,7 +4,6 @@ from dcim.models import Device, DeviceRole, DeviceType, Site
 from ipam.models import Prefix
 from virtualization.models import VirtualMachine
 from extras.models import Tag
-from core.models import Job
 from .models import AWXInventory
 from .serializers import (
     serializers_dict,
@@ -14,8 +13,6 @@ from .serializers import (
 from django_rq import get_queue
 from rq import get_current_job, Queue
 from requests.exceptions import RequestException, HTTPError, ConnectionError, Timeout
-from urllib3.exceptions import InsecureRequestWarning
-import urllib3
 
 # Set up logging
 logger = logging.getLogger(__name__)
@@ -195,24 +192,155 @@ def delete_group(inventory, sender, instance):
 
 def sync_all(job):
     """
-    Performs a full synchronization of the AWX inventory.
+    Performs a full synchronization of the AWX inventory, including host-group associations.
+    Optimized to check for existing groups and hosts before creating or updating them.
     """
     inventory = job.object
-    logger.info(f"Performing full inventory sync for inventory {inventory.inventory_id}")
+    logger.info(
+        f"Performing full inventory sync for inventory {inventory.inventory_id}"
+    )
     job.start()
-    for site in Site.objects.all():
-        sync_group(inventory, Site, site)
-    for device_role in DeviceRole.objects.all():
-        sync_group(inventory, DeviceRole, device_role)
-    for device_type in DeviceType.objects.all():
-        sync_group(inventory, DeviceType, device_type)
-    for tag in Tag.objects.all():
-        sync_group(inventory, Tag, tag)
-
-    for device in Device.objects.all():
-        if device.primary_ip4 and device.primary_ip4.dns_name:
-            sync_host(inventory, Device, device)
-    for vm in VirtualMachine.objects.all():
-        if vm.primary_ip4 and vm.primary_ip4.dns_name:
-            sync_host(inventory, VirtualMachine, vm)
+
+    # Collect all AWX groups and hosts
+    awx_groups = inventory.get_all_groups()
+    awx_hosts = inventory.get_all_hosts()
+
+    # Synchronize groups
+    group_models = [Site, DeviceRole, DeviceType, Prefix, Tag]
+    netbox_group_names = set()
+    for model in group_models:
+        instances = model.objects.all()
+        for instance in instances:
+            serializer = serializers_dict[model](instance)
+            group_name = serializer.data["name"]
+            netbox_group_names.add(group_name)
+
+            if group_name in awx_groups:
+                # Group exists in AWX, check if it needs updating
+                awx_group = awx_groups[group_name]
+                awx_group_serializer = AWXGroupSerializer(data=awx_group)
+                if awx_group_serializer.is_valid():
+                    awx_group_data = awx_group_serializer.validated_data
+                    if awx_group_data != serializer.data:
+                        inventory.update_group(awx_group["id"], serializer.data)
+                        logger.info(f"Updated group {group_name} in AWX.")
+                else:
+                    logger.error(f"Invalid data for awx_group_serializer: {awx_group_serializer.errors}")
+            else:
+                # Group does not exist in AWX, create it
+                awx_group = inventory.create_group(serializer.data)
+                if awx_group:
+                    logger.info(f"Created group {group_name} in AWX.")
+                    # Update local cache
+                    awx_groups[group_name] = awx_group
+                else:
+                    logger.error(
+                        f"Failed to create group {group_name} in AWX."
+                    )
+
+    awx_group_names = set(awx_groups.keys())
+    # Delete groups in AWX that are not in NetBox
+    groups_to_delete = awx_group_names - netbox_group_names
+    for group_name in groups_to_delete:
+        inventory.delete_group(group_name)
+        logger.info(f"Deleted group {group_name} from AWX as it no longer exists in NetBox.")
+
+    # Synchronize hosts
+    host_models = [Device, VirtualMachine]
+    netbox_host_names = set()
+    for model in host_models:
+        instances = model.objects.select_related(
+            "primary_ip4"
+        ).prefetch_related("interfaces__ip_addresses")
+        for instance in instances:
+            if not (instance.primary_ip4 and instance.primary_ip4.dns_name):
+                continue
+            serializer = serializers_dict[model](instance)
+            host_name = serializer.data["name"]
+            netbox_host_names.add(host_name)
+
+            if host_name in awx_hosts:
+                # Host exists in AWX, check if it needs updating
+                awx_host = awx_hosts[host_name]
+                awx_host_serializer = AWXHostSerializer(data=awx_host)
+                if awx_host_serializer.is_valid():
+                    awx_host_data = awx_host_serializer.validated_data
+                    if awx_host_data != serializer.data:
+                        inventory.update_host(awx_host["id"], serializer.data)
+                        logger.info(f"Updated host {host_name} in AWX.")
+                    host_id = awx_host["id"]
+                else:
+                    logger.error(f"Invalid data for awx_host_serializer: {awx_host_serializer.errors}")
+                    continue  # Skip this host or handle the error appropriately
+            else:
+                # Host does not exist in AWX, create it
+                awx_host = inventory.create_host(serializer.data)
+                if awx_host:
+                    logger.info(f"Created host {host_name} in AWX.")
+                    # Update local cache
+                    awx_hosts[host_name] = awx_host
+                    host_id = awx_host["id"]
+                else:
+                    logger.error(
+                        f"Failed to create host {host_name} in AWX."
+                    )
+                    continue  # Skip to the next host or handle the error as appropriate
+
+            # Synchronize host-group associations
+            if awx_host["summary_fields"]["groups"]["count"] > len(
+                awx_host["summary_fields"]["groups"]["results"]
+            ):
+                current_groups = inventory.get_host_groups(host_id)
+            else:
+                current_groups = awx_host["summary_fields"]["groups"]["results"]
+            current_group_names = set(group["name"] for group in current_groups)
+
+            valid_group_names = set()
+            # Collect valid group names for this host
+            if hasattr(instance, 'site') and instance.site:
+                group_name = f"{group_prefixes[Site]}{instance.site.slug.replace('-', '_')}"
+                valid_group_names.add(group_name)
+            if hasattr(instance, 'role') and instance.role:
+                group_name = f"{group_prefixes[DeviceRole]}{instance.role.slug.replace('-', '_')}"
+                valid_group_names.add(group_name)
+            if isinstance(instance, Device) and instance.device_type:
+                group_name = f"{group_prefixes[DeviceType]}{instance.device_type.slug.replace('-', '_')}"
+                valid_group_names.add(group_name)
+            if hasattr(instance, 'tags'):
+                tags = instance.tags.all()
+                for tag in tags:
+                    group_name = f"{group_prefixes[Tag]}{tag.slug.replace('-', '_')}"
+                    valid_group_names.add(group_name)
+
+            # Associate host with missing groups
+            groups_to_associate = valid_group_names - current_group_names
+            for group_name in groups_to_associate:
+                group = awx_groups.get(group_name)
+                if group:
+                    inventory.associate_host_group(host_id, group["id"])
+                    logger.info(
+                        f"Associated host {host_name} with group {group_name}."
+                    )
+                else:
+                    logger.error(
+                        f"Group {group_name} not found in AWX when trying to associate with host {host_name}."
+                    )
+
+            # Disassociate host from groups that are no longer valid
+            groups_to_disassociate = current_group_names - valid_group_names
+            for group_name in groups_to_disassociate:
+                group = awx_groups.get(group_name)
+                if group:
+                    inventory.disassociate_host_group(host_id, group["id"])
+                    logger.info(
+                        f"Disassociated host {host_name} from group {group_name}."
+                    )
+
+    # Delete hosts in AWX that are not in NetBox
+    awx_host_names =set(awx_hosts.keys())
+    hosts_to_delete = awx_host_names - netbox_host_names
+    for host_name in hosts_to_delete:
+        inventory.delete_host(host_name)
+        logger.info(f"Deleted host {host_name} from AWX as it no longer exists in NetBox.")
+
     job.terminate()
diff --git a/netbox_awx_plugin/tests/test_synchronization.py b/netbox_awx_plugin/tests/test_synchronization.py
index 7e7a0df422748c2bb97f08653363f912264ab312..8ef3b18326a875bc84dd80ed1da7162bc6ee26e8 100644
--- a/netbox_awx_plugin/tests/test_synchronization.py
+++ b/netbox_awx_plugin/tests/test_synchronization.py
@@ -259,15 +259,60 @@ class SynchronizationTestCase(TestCase):
         # Ensure that associate_host_group was called
         mock_associate_host_group.assert_called_with(1, 2)
 
-    @patch('netbox_awx_plugin.synchronization.sync_host')
-    @patch('netbox_awx_plugin.synchronization.sync_group')
-    def test_sync_all(self, mock_sync_group, mock_sync_host):
+    @patch('netbox_awx_plugin.models.AWXInventory.disassociate_host_group')
+    @patch('netbox_awx_plugin.models.AWXInventory.associate_host_group')
+    @patch('netbox_awx_plugin.models.AWXInventory.get_host_groups')
+    @patch('netbox_awx_plugin.models.AWXInventory.get_group')
+    @patch('netbox_awx_plugin.models.AWXInventory.get_host')
+    @patch('netbox_awx_plugin.models.AWXInventory.get_all_groups')
+    @patch('netbox_awx_plugin.models.AWXInventory.create_group')
+    @patch('netbox_awx_plugin.models.AWXInventory.update_group')
+    @patch('netbox_awx_plugin.models.AWXInventory.get_all_hosts')
+    @patch('netbox_awx_plugin.models.AWXInventory.create_host')
+    @patch('netbox_awx_plugin.models.AWXInventory.update_host')
+    def test_sync_all(self, mock_update_host, mock_create_host, mock_get_all_hosts,
+                      mock_update_group, mock_create_group, mock_get_all_groups,
+                      mock_get_host, mock_get_group, mock_get_host_groups,
+                      mock_associate_host_group, mock_disassociate_host_group):
+        # Mock return values
+        mock_get_all_groups.return_value = {}
+        mock_get_all_hosts.return_value = {}
+        mock_create_group.return_value = {
+            'id': 1,
+            'name': 'site_test_site',
+            'description': '',
+            'variables': ''
+        }
+        mock_create_host.return_value = {
+            'id': 1,
+            'name': 'test-device.example.com',
+            'summary_fields': {
+                'groups': {
+                    'count': 0,
+                    'results': []
+                }
+            },
+            'variables': '',
+            'description': '',
+            'enabled': True
+        }
+
+        mock_get_host.return_value = mock_create_host.return_value
+        mock_get_group.return_value = mock_create_group.return_value
+        mock_get_host_groups.return_value = []
+
         job = Mock()
         job.object = self.awx_inventory
         sync_all(job)
-        # Ensure that sync_host and sync_group are called appropriately
-        self.assertTrue(mock_sync_group.called)
-        self.assertTrue(mock_sync_host.called)
+
+        # Ensure that create_group and create_host are called
+        mock_create_group.assert_called()
+        mock_create_host.assert_called()
+        # Ensure that associate_host_group is called
+        mock_associate_host_group.assert_called_with(1, 1)
+
+
+
 
     # Additional tests for helper functions
     def test_sync_host_group_association(self):