---
title: Service Discovery
description: Query, filter, and inspect services in the container
---

Vessel provides service discovery APIs for querying registered services by lifecycle, group, metadata, or started status.

## Querying Services

`Query` accepts a `ServiceQuery` struct and returns `[]ServiceInfo` for all matching services.

```go
import "github.com/xraph/vessel"

// Find all singleton services that have been started
started := true
results := vessel.Query(c, vessel.ServiceQuery{
    Lifecycle: "singleton",
    Started:   &started,
})

for _, info := range results {
    fmt.Printf("%s: lifecycle=%s started=%v\n", info.Name, info.Lifecycle, info.Started)
}
```

### ServiceQuery Fields

| Field | Type | Description |
|---|---|---|
| `Lifecycle` | `string` | Filter by lifecycle: `"singleton"`, `"transient"`, `"scoped"`. Empty matches all. |
| `Group` | `string` | Filter by service group name. Empty matches all. |
| `Metadata` | `map[string]string` | All specified key-value pairs must match. |
| `Started` | `*bool` | Filter by started status. `nil` matches all. |

### QueryNames

When you only need service names (more efficient than full `Query`):

```go
names := vessel.QueryNames(c, vessel.ServiceQuery{
    Group: "api-handlers",
})
// names is []string
```

## Convenience Finders

```go
// All services in a group
apiHandlers := vessel.FindByGroup(c, "api-handlers")

// All singletons
singletons := vessel.FindByLifecycle(c, "singleton")

// All started services
running := vessel.FindStarted(c)

// All services not yet started
pending := vessel.FindNotStarted(c)
```

## Listing and Inspecting

The container itself provides lower-level inspection:

```go
// List all registered service names
names := c.Services()

// Inspect a specific service
info := c.Inspect("database")
fmt.Printf("Name: %s\n", info.Name)
fmt.Printf("Lifecycle: %s\n", info.Lifecycle)
fmt.Printf("Started: %v\n", info.Started)
fmt.Printf("Metadata: %v\n", info.Metadata)

// Check existence
if c.Has("cache") {
    fmt.Println("Cache is registered")
}

// Check started status
if c.IsStarted("database") {
    fmt.Println("Database is running")
}
```
