# Getting Started with NATS CLI

# What is NATS?

The technology landscape is full of *message brokers* and *event/message buses*: Kafka, Event Hub, Pulsar, SQS, Google Pub/Sub, and more in no particular order. In this crowded space, NATS stands out as a unique perspective of the connectivity problem space. Beyond simply passing messages around, NATS is oriented toward solving application connectivity from a first principles like foundation.

At first glance, NATS is a message bus, it facilitates location transparent Pub/Sub. But upon that, so much more can be built, and complex, nuanced patterns can be expressed. Basic Fan-Out/In Pub/Sub, Work Queue Distribution, Request/Reply semantics, Weighted & Mapped Routing, etc. Capabilities like this allow us a new way to approach the connectivity problem space. When we might traditionally reach for HTTP REST, or complex load balanced ingress, NATS provides an elegant alternative. And this is just with Core NATS before we dig into JetStream persistence, Key-Value Semantics, Object Storage, NEX Workloads, etc.

# Where do we start?

In this introduction we’re going to accomplish three main objectives:

1. Install our tooling and stand up a NATS server
    
2. Pub/Sub messages using *Subject* based addressing
    
3. Execute Request/Reply built on top of Pub/Sub
    

---

# Tooling

## NATS CLI

First, install the [NATS CLI tool](https://docs.nats.io/using-nats/nats-tools/nats_cli), this is the unified tool to interact with the NATS server. From the CLI we can Pub/Sub, Request/Reply, manage Streams, Benchmark, etc. The tool can be installed a variety of ways as documented in the [GitHub README](https://github.com/nats-io/natscli?tab=readme-ov-file#installation) and the binaries are available in [GitHub Releases](https://github.com/nats-io/natscli/releases). For instance, you can leverage `go` and install the latest with

```powershell
go install github.com/nats-io/natscli/nats@latest
```

Ensure `NATS` has been added to your `$PATH` and with the following you should see the latest version you have

```powershell
nats --version
0.2.2
```

Conveniently, in addition to the typical `-h, --help` the CLI gives a selection of “cheat sheets” via `nats cheat {cheat}`. Looking through these will really help understanding how to work with the tool and what can be done with it.

```powershell
nats cheat
Available Cheats:
    account
    auth
    bench
    consumer
    contexts
    errors
    events
    kv
    latency
    obj
    pub
    reply
    schemas
    server
    stream
    sub
```

## NATS Server

Next, you’ll need the `nats-server`, this is the core of it all and a single feature packed binary. The binary itself can be [downloaded via NATS.io](https://nats.io/download/), alternatively `nats-server` can be easily spun up in Docker/Podman. Here, I’ll use Docker and we’re going to configure a couple of items.

1. We’ll expose the default NATS port 4222 and the default monitoring port 8222
    
2. Name the NATS server instance with `-n nats1`
    
3. Enable NATS monitoring via `-m 8222`
    

```powershell
docker run --rm --name my-nats -p "4222:4222" -p "8222:8222" nats -n nats1 -m 8222
```

```powershell
[1] [INF] Starting nats-server
[1] [INF]   Version:  2.11.1
[1] [INF]   Git:      [d78523b]
[1] [INF]   Name:     nats1
[1] [INF]   ID:       ND6JF5FBLCHPSUBLSAJRLSHWANFQ2D6RJWSK3XJDFBIX5RTE3NQDH5ER
[1] [INF] Starting http monitor on *******:8222
[1] [INF] Listening for client connections on *******:4222
[1] [INF] Server is ready
```

---

# Pub/Sub - NATS CLI

With our NATS server running, let’s begin with the simplest expression of NATS, Pub/Sub. Open three new terminals, two for subscription and one for publishing.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1746761731693/28bd1951-fb68-4fef-9b66-0c5ec8570ee9.png align="center")

Next, separately begin two subscriptions with `nats sub`

```powershell
nats sub some.subject
```

Executing this in both subscription terminals should yield some like this

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1746761748747/f1a15b64-ee4f-4498-a607-a710515a15e5.png align="center")

Finally, let’s publish a message with `nats pub` and see it delivered to both subscribers.

From the **NATS Pub** terminal execute

```powershell
nats pub some.subject "Hello World"
```

Altogether, we should see the message published and received by both subscribers

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1746680596509/7b616cf1-8402-4479-b49a-6d8879f73bd6.png align="center")

## Adding Headers

Just for fun, let’s add a *Header* to our message, similar to HTTP Headers, these are Key/Value pairs that support multiple values. These can be used to pass metadata, or as we get more advanced can enable deduplication, optimistic concurrency, etc.

Execute the following `nats pub` command, passing a generic `Content-Type` header

```powershell
nats pub some.subject --header "Content-Type:text/plain" "Hello World"
```

Altogether we should see the new output

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1746680709883/ff850b51-ef6b-47aa-b669-30fd140bdbb5.png align="center")

## Using Queue Groups

Previously, the published message was delivered to *all* subscribers, i.e. if we had 100 subscribers, every one would receive the message. However, sometimes we want to distribute messages to a group of subscribers. This is similar to the concept of a work queue, where each message is handled by one and only one subscriber.

To express this pattern in NATS we use a *Queue Group*. Defined on the subscription, all subscribers within the same group will share responsibility for a subject. NATS will deliver each message to one subscriber in via a nearly random selection that tends towards an even distribution.

Seeing it action, start two new subscriptions with the following command

```powershell
nats sub some.subject --queue my_group
```

Then we can publish again

```powershell
nats pub some.subject "Hello World"
```

And in result we should see that only one subscriber received the message

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1746680808160/db71e266-8acf-4cb3-9a62-ac2d6b5a2b10.png align="center")

Note though, subscriptions outside the *Queue Group* and in other groups, are still delivered the message

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1746680905958/a262df2c-cab0-4cce-87dc-dda5ee90c1c5.png align="center")

# Request/Reply - NATS CLI

Another common communication pattern is Request/Reply, where we expect a single reply for a given request. While this pattern is engrained within something like an HTTP call, NATS expresses this pattern from the basis of Pub/Sub. A *Request* is published while a temporary *Inbox* is formed and subscribed to by the “Requestor”, any subscriber can then *Reply* to the *Request* on the provided *Inbox* subject.

Let’s see it in action! First, open a new terminal and stand up a “Responder” to *Requests*

```powershell
nats reply some.subject "Responded @ {{Time}}"
```

Then, from our **NATS Pub** terminal issue the *Request*

```powershell
nats request some.subject "Hello World"
```

And we should see the *Reply* returned back to our requestor as expected

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1746681049027/5c831573-9b59-46b3-b134-7db8e448022c.png align="center")

We’ll discuss this deeper when we code a Request/Reply pattern, but this illustrates the basic concept. Also note, that we published on the same *Subject* as before, our earlier *Subscribers* still received the new message, although they aren’t going to respond to our *Request*, still, interest in the *Subject* is respected and the message delivered.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1746681162263/71ae59f7-9154-49ca-a1ec-724af0ca0ce6.png align="center")

---

# Wrap Up

In this introduction we got familiar with standing up a NATS Server via Docker. Next, we got acquainted with the NATS CLI and its basic Pub/Sub, Request/Reply capabilities. With just a few commands, a single container, we’re already publishing and subscribing with location transparent and subject aware messaging. Our NATS Server, Publisher, and Subscribers can easily be globally remote from one another, and given access, could just as easily communicate. Clearly, we’re just beginning so stay tuned and we’ll keep exploring.

Have a specific question about NATS? Want a specific topic covered? Drop it in the comments!
