---
layout: docs
page_title: Define services
description: >-
    Learn how to define services so that they are discoverable in your network.
---

# Define services

This topic describes how to define services so that they can be discovered by other services. Refer to [Services Overview](/consul/docs/services/services) for additional information.

## Overview

You must tell Consul about the services deployed to your network if you want them to be discoverable. You can define services in a configuration file or send the service definition parameters as a payload to the `/agent/service/register` API endpoint. Refer to [Register Services and Health Checks](/consul/docs/services/usage/register-services-checks) for details about how to register services with Consul.

You can define multiple services individually using `service` blocks or group multiple services into the same `services` configuration block. Refer to [Define multiple services in a single file](#define-multiple-services-in-a-single-file) for additional information.

If Consul service mesh is enabled in your network, you can use the [service defaults configuration entry](/consul/docs/connect/config-entries/service-defaults) to specify default global values for services. The configuration entry lets you define common service parameter, such as upstreams, namespaces, and partitions. Refer to [Define service defaults](#define-service-defaults) for additional information.

## Requirements

The core service discovery features are available in all versions of Consul.

### Service defaults
To use the [service defaults configuration entry](#define-service-defaults), verify that your installation meets the following requirements:

- Consul 1.5.0+
- Consul 1.8.4+ is required to use the `ServiceDefaults` custom resource on Kubernetes

### ACLs
If ACLs are enabled, resources in your network must present a token with `service:read` access to read a service defaults configuration entry.

You must also present a token with `service:write` access to create, update, or delete a service defaults configuration entry.

Service configurations must also contain and present an ACL token to perform anti-entropy syncs and deregistration operations. Refer to [Modify anti-entropy synchronization](#modify-anti-entropy-synchronization) for additional information.

On Consul Enterprise, you can register services with specific namespaces if the services' ACL tokens are scoped to the namespace. Services registered with a service definition do not inherit the namespace associated with the ACL token specified in the `token` field. The `namespace` and the `token` parameters must be included in the service definition for the service to be registered to the namespace that the ACL token is scoped to.

## Define a service
Create a file for your service configurations and add a `service` block. The `service` block contains the parameters that configure various aspects of the service, including how it is discovered by other services in the network. The only required parameter is `name`. Refer to [Service Definition Reference](/consul/docs/services/configuration/services-configuration-reference) for details about the configuration options.

For Kubernetes environments, you can enable the  [`connectInject`](/consul/docs/k8s/connect#installation-and-configuration) configuration in your Consul Helm chart so that Consul automatically adds a sidecar to each of your pods. Consul uses the Kubernetes `Service` definition as a reference.

The following example defines a service named `redis` that is available on port `80`. By default, the service has the IP address of the agent node.

<CodeTabs>
<CodeBlockConfig heading="service.hcl">

```hcl
service {
  name = "redis"
  id   = "redis"
  port = 80
  tags = ["primary"]

  meta = {
    custom_meta_key = "custom_meta_value"
  }

  tagged_addresses = {
    lan = {
      address = "192.168.0.55"
      port    = 8000
    }

    wan = {
      address = "198.18.0.23"
      port    = 80
    }
  }
}
```

</CodeBlockConfig>
<CodeBlockConfig heading="service.json">

```json
{
  "service": [
    {
      "id": "redis",
      "meta": [
        {
          "custom_meta_key": "custom_meta_value"
        }
      ],
      "name": "redis",
      "port": 80,
      "tagged_addresses": [
        {
          "lan": [
            {
              "address": "192.168.0.55",
              "port": 8000
            }
          ],
          "wan": [
            {
              "address": "198.18.0.23",
              "port": 80
            }
          ]
        }
      ],
      "tags": [
        "primary"
      ]
    }
  ]
}
```
</CodeBlockConfig>
</CodeTabs>

### Health checks

You can add a `check` or `checks` block to your service configuration to define one or more health checks that monitor the health of your services. Refer to [Define Health Checks](/consul/docs/services/usage/checks) for additional information.

### Register a service

You can register your service using the [`consul services` command](/consul/commands/services) or by calling the [`/agent/services` API endpoint](/consul/api-docs/agent/service). Refer to [Register Services and Health Checks](/consul/docs/services/usage/register-services-checks) for details.

## Define service defaults
If Consul service mesh is enabled in your network, you can define default values for services in your mesh by creating and applying a `service-defaults` configuration entry containing. Refer to [Service Mesh Configuration Overview](/consul/docs/connect/configuration) for additional information.

Create a file for the configuration entry and specify the required fields. If you are authoring `service-defaults` in HCL or JSON, the `Kind` and `Name` fields are required. On Kubernetes, the `apiVersion`, `kind`, and `metadata.name` fields are required. Refer to [Service Defaults Reference](/consul/docs/connect/config-entries/service-defaults) for details about the configuration options.

If you use Consul Enterprise, you can also specify the `Namespace` and `Partition` fields to apply the configuration to services in a specific namespace or partition. For Kubernetes environments, the configuration entry is always created in the same partition as the Kubernetes cluster.

### Consul OSS example
The following example instructs services named `counting` to send up to `512` concurrent requests to a mesh gateway:

<CodeTabs tabs={[ "HCL", "Kubernetes YAML", "JSON" ]}>

```hcl
Kind = "service-defaults"
Name = "counting"

UpstreamConfig = {
  Defaults = {
    MeshGateway = {
      Mode = "local"
    }
    Limits = {
      MaxConnections = 512
      MaxPendingRequests = 512
      MaxConcurrentRequests = 512
    }
  }

  Overrides = [
    {
      Name = "dashboard"
      MeshGateway = {
        Mode = "remote"
      }
    }
  ]
}
```
```yaml
apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceDefaults
metadata:
  name: counting
spec:
  upstreamConfig:
    defaults:
      meshGateway:
        mode: local
      limits:
        maxConnections: 512
        maxPendingRequests: 512
        maxConcurrentRequests: 512
    overrides:
      - name: dashboard
        meshGateway:
          mode: remote
```
```json
{
  "Kind": "service-defaults",
  "Name": "counting",
  "UpstreamConfig": {
    "Defaults": {
      "MeshGateway": {
        "Mode": "local"
      },
      "Limits": {
        "MaxConnections": 512,
        "MaxPendingRequests": 512,
        "MaxConcurrentRequests": 512
      }
    },
    "Overrides": [
      {
        "Name": "dashboard",
        "MeshGateway": {
          "Mode": "remote"
        }
      }
    ]
  }
}
```
</CodeTabs>

### Consul Enterprise example
The following example instructs services named `counting` in the `prod` namespace to send up to `512` concurrent requests to a mesh gateway:

<CodeTabs tabs={[ "HCL", "Kubernetes YAML", "JSON" ]}>

```hcl
Kind = "service-defaults"
Name = "counting"
Namespace = "prod"

UpstreamConfig = {
  Defaults = {
    MeshGateway = {
      Mode = "local"
    }
    Limits = {
      MaxConnections = 512
      MaxPendingRequests = 512
      MaxConcurrentRequests = 512
    }
  }

  Overrides = [
    {
      Name = "dashboard"
      MeshGateway = {
        Mode = "remote"
      }
    }
  ]
}
```
```yaml
apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceDefaults
metadata:
  name: counting
  namespace: prod
spec:
  upstreamConfig:
    defaults:
      meshGateway:
        mode: local
      limits:
        maxConnections: 512
        maxPendingRequests: 512
        maxConcurrentRequests: 512
    overrides:
      - name: dashboard
        meshGateway:
          mode: remote
```
```json
{
  "Kind": "service-defaults",
  "Name": "counting",
  "Namespace" : "prod",
  "UpstreamConfig": {
    "Defaults": {
      "MeshGateway": {
        "Mode": "local"
      },
      "Limits": {
        "MaxConnections": 512,
        "MaxPendingRequests": 512,
        "MaxConcurrentRequests": 512
      }
    },
    "Overrides": [
      {
        "Name": "dashboard",
        "MeshGateway": {
          "Mode": "remote"
        }
      }
    ]
  }
}
```
</CodeTabs>

### Apply service defaults

You can apply your `service-defaults` configuration entry using the [`consul config` command](/consul/commands/config) or by calling the [`/config` API endpoint](/consul/api-docs/config). In Kubernetes environments, apply the `service-defaults` custom resource definitions (CRD) to implement and manage Consul configuration entries.

Refer to the following topics for details about applying configuration entries:
- [How to Use Configuration Entries](/consul/docs/agent/config-entries)
- [Custom Resource Definitions for Consul on Kubernetes](/consul/docs/k8s/crds)

## Define multiple services in a single file

The `services` block contains an array of `service` objects. It is a wrapper that enables you to define multiple services in the service definition and instruct Consul to expect more than just a single service configuration. As a result, you can register multiple services in a single `consul services register` command. Note that the `/agent/service/register` API endpoint does not support the `services` parameter.

In the following example, the service definition configures an instance of the `redis` service tagged as `primary` running on port `6000`. It also configures an instance of the service tagged as `secondary` running on port `7000`.

<CodeTabs heading="Multiple Service Definitions">

<CodeBlockConfig filename="redis-services.hcl">

```hcl
services {
  id = "red0"
  name = "redis"
  tags = [
    "primary"
  ]
  address = ""
  port = 6000
  checks = [
    {
      args = ["/bin/check_redis", "-p", "6000"]
      interval = "5s"
      timeout = "20s"
    }
  ]
}
services {
  id = "red1"
  name = "redis"
  tags = [
    "delayed",
    "secondary"
  ]
  address = ""
  port = 7000
  checks = [
    {
      args = ["/bin/check_redis", "-p", "7000"]
      interval = "30s"
      timeout = "60s"
    }
  ]
}

```

</CodeBlockConfig>

<CodeBlockConfig filename="redis-services.json">

```json
{
  "services": [
    {
      "id": "red0",
      "name": "redis",
      "tags": [
        "primary"
      ],
      "address": "",
      "port": 6000,
      "checks": [
        {
          "args": ["/bin/check_redis", "-p", "6000"],
          "interval": "5s",
          "timeout": "20s"
        }
      ]
    },
    {
      "id": "red1",
      "name": "redis",
      "tags": [
        "delayed",
        "secondary"
      ],
      "address": "",
      "port": 7000,
      "checks": [
        {
          "args": ["/bin/check_redis", "-p", "7000"],
          "interval": "30s",
          "timeout": "60s"
        }
      ]
    }
  ]
}
```

</CodeBlockConfig>
</CodeTabs>

## Modify anti-entropy synchronization

By default, the Consul agent uses anti-entropy mechanisms to maintain information about services and service health, and synchronize local states with the Consul catalog. You can enable the `enable_tag_override` option in the service configuration, which lets external agents change the tags for a service. This can be useful in situations where an external monitoring service needs to be the source of truth for tag information. Refer [Anti-entropy](/consul/docs/architecture/anti-entropy) for details.

Add the `enable_tag_override` option to the `service` block and set the value to `true`:

<CodeTabs tabs={[ "HCL","JSON" ]}>

<CodeBlockConfig highlight="4">

```hcl
service {
  name = "redis"
  port = 6379
  enable_tag_override = true
}
```

</CodeBlockConfig>

<CodeBlockConfig highlight="5">

```json
{
  "service": {
    "name": "redis",
    "port": 6379,
    "enable_tag_override": true
  }
}
```

</CodeBlockConfig>

</CodeTabs>

This configuration only applies to the locally registered service. Nodes that register the same service apply the `enable_tag_override` and other service configurations independently. The tags for a service registered on one node update are not affected by operations performed on services with the same name registered on other nodes.

Refer to [`enable_tag_override`](/consul/docs/services/configuration/services-configuration-reference#enable_tag_override) for additional configuration information.

## Services in service mesh environments
Defining services for service mesh environments on virtual machines and in Kubernetes requires a different workflow.

### Define service mesh proxies
You can register services to function as service mesh or sidecar proxies so that they can facilitate communication between other services across your network. Refer to [Service Mesh Proxy Overview](/consul/docs/connect/registration) for additional information.

### Define services in Kubernetes
You can enable the services running in Kubernetes and Consul to sync automatically. Doing so ensures that Kubernetes services are available to Consul agents and services in Consul can be available as first-class Kubernetes services. Refer to [Service Sync for Consul on Kubernetes](/consul/docs/k8s/service-sync) for details.
