# Define services
> Services group multiple versioned attribute groups into stable consumption interfaces for applications. Create and manage services to control which attribute versions your applications use.
> Source: https://docs.snowplow.io/docs/signals/applications/services/
> Documentation index: https://docs.snowplow.io/llms.txt

[Services](/docs/signals/concepts/#services) group attribute groups together for serving to your applications. They provide a stable interface for [retrieving attributes](/docs/signals/applications/retrieve-attributes/): we strongly recommend using services in production applications.

The Node.js SDK reads services but can't create them. Use Console or the Python SDK to define services.

A service can include both stream attribute groups and [warehouse attribute groups](/docs/signals/attributes/warehouse-config/). If they use the same attribute key, one request to the service returns the real-time and warehouse attributes for that user together.

**Console:**

To create a service, go to **Signals** > **Services** in Snowplow Console and follow the instructions.

![Create service form with name, description, owner, and attribute group selection](/assets/images/service-create-85585d669c129ebb7cb30d74209dfc12.png)

To configure a service, you'll need to specify:

- A unique name
- An optional description
- The email address of the primary owner or maintainer
- Which attribute groups to include

**Python SDK:**

Use the `Service` class to define a service. You can refer to attribute groups either by passing the objects directly, or by name and version using a dictionary:

```python
from snowplow_signals import Service

# Refer to attribute groups by name and version
my_service = Service(
    name='my_service',
    description='A collection of attribute groups',
    owner="user@company.com",
    attribute_groups=[
        {"name": "user_attributes", "version": 2},
        {"name": "session_attributes", "version": 1},
    ],
)

# Or pass the objects directly
my_service = Service(
    name='my_service',
    description='A collection of attribute groups',
    owner="user@company.com",
    attribute_groups=[
        my_attribute_group,
        another_attribute_group,
    ],
)
```

This table lists all available arguments for a `Service`:

| Argument           | Description                                                  | Type                             | Required? |
| ------------------ | ------------------------------------------------------------ | -------------------------------- | --------- |
| `name`             | The name of the service                                      | `string`                         | ✅         |
| `description`      | A description of the service                                 | `string`                         | ❌         |
| `owner`            | The owner of the service                                     | `string`                         | ✅         |
| `attribute_groups` | List of attribute groups with optional version specification | list of `AttributeGroup` or dict | ❌         |

***

## Versioning

When choosing which attribute groups to include, you'll select a specific version of each attribute group.

Services themselves are not versioned. You can update them to use different attribute groups, or different attribute group versions, at any time.

**Console:**

![Service configuration showing selected attribute groups with version numbers](/assets/images/service-groups-adfabeee05def063578d69fda35203b2.png)

**Python SDK:**

Specify the version of each attribute group in the `attribute_groups` list using a dictionary with `name` and `version` keys, or by using a versioned `AttributeGroup` object directly.

***

## Manage services

**Console:**

Services are automatically published as soon as they're created. They're a wrapper for consuming calculated attributes, and don't cause any additional processing themselves.

To edit a service definition, go to the service details page and click the **Edit** button.

To delete a service, go to the service details page and click the `⋮` button, then choose **Delete**.

![Signals service details page in Snowplow Console showing the Edit button and the three-dot overflow menu expanded with the Delete option](/assets/images/service-edit-delete-7e8bf6d7c7571a961344c7d77b47263b.png)

**Python SDK:**

Use `publish()` to register services with Signals.

```python
import os
from snowplow_signals import Signals

sp_signals = Signals(
    api_url=os.environ["SIGNALS_API_URL"],
    api_key=os.environ["SNOWPLOW_API_KEY"],
    api_key_id=os.environ["SNOWPLOW_API_KEY_ID"],
    org_id=os.environ["SNOWPLOW_ORG_ID"],
)

# my_service and my_other_service: services defined as in Create a service
sp_signals.publish([
    my_service,
    my_other_service,
])
```

***
