# How to Configure and Use Namespace Isolation in CoSky

> Learn to configure and use namespace isolation in CoSky for multi-tenant applications. Master resource isolation via spring.cloud.cosky.namespace for efficient tenant management.

- Repository: [Ahoo Wang/cosky](https://github.com/ahoo-wang/cosky)
- Tags: how-to-guide
- Published: 2026-02-23

---

**CoSky isolates resources by namespace—a logical tenant identifier prefixed to every Redis key and REST API path—enabling multi-tenant configuration and service discovery through the `spring.cloud.cosky.namespace` property or runtime context switching.**

Namespace isolation in CoSky provides the foundation for multi-tenancy in distributed systems. The `ahoo-wang/cosky` repository implements this pattern across three architectural layers: configuration properties, runtime thread-local context, and REST API path variables. Each namespace maintains independent config data, service discovery metadata, and RBAC policies within the same Redis backend.

## Understanding Namespace Isolation Architecture

CoSky applies namespace isolation at three distinct layers to ensure complete tenant separation.

### Configuration Layer

The `spring.cloud.cosky.namespace` property sets the default tenant identifier for the entire application. When omitted, CoSky falls back to `Namespaced.DEFAULT` (value: `"cosky"`). This value is defined in [`CoSkyProperties.kt`](https://github.com/ahoo-wang/cosky/blob/main/CoSkyProperties.kt) and represents the root of all key prefixes stored in Redis.

### Runtime Context Layer

At startup, `CoSkyAutoConfiguration` copies the property value into `NamespacedContext.namespace`, a thread-local holder that downstream components reference. All internal services—including `ConfigService`, `DiscoveryService`, and `NamespaceService`—read the current namespace from this context, ensuring operations remain scoped to the active tenant.

### REST API Layer

Every tenant-scoped endpoint includes a `{namespace}` path variable under the `/v1/namespaces/{namespace}` prefix. Controllers extract this variable and forward it to the service layer, as implemented in [`RequestPathPrefix.kt`](https://github.com/ahoo-wang/cosky/blob/main/RequestPathPrefix.kt) and consumed by controllers like [`ServiceController.kt`](https://github.com/ahoo-wang/cosky/blob/main/ServiceController.kt).

## Configuring the Default Namespace

Set the default namespace in [`application.yaml`](https://github.com/ahoo-wang/cosky/blob/main/application.yaml) (or [`bootstrap.yaml`](https://github.com/ahoo-wang/cosky/blob/main/bootstrap.yaml) if required before the Spring context starts):

```yaml
spring:
  cloud:
    cosky:
      # The tenant identifier used when no explicit namespace is provided

      namespace: my-company

```

When this property is present, [`CoSkyAutoConfiguration.kt`](https://github.com/ahoo-wang/cosky/blob/main/CoSkyAutoConfiguration.kt) executes:

```kotlin
// CoSkyAutoConfiguration.kt (excerpt)
NamespacedContext.namespace = coSkyProperties.namespace

```

All components using `NamespacedContext.namespace` automatically operate within the `my-company` tenant. This configuration affects config resolution, service registration, and permission checks throughout the application lifecycle.

## Switching Namespaces at Runtime

For multi-tenant SaaS scenarios requiring dynamic tenant switching, inject the **`NamespaceService`** bean:

```kotlin
@Service
class TenantInitializer(
    private val namespaceService: NamespaceService
) {
    fun switchTo(tenant: String): Mono<Void> =
        namespaceService.setNamespace(tenant)   // Updates thread-local context
}

```

The `NamespaceService` API (defined in [`NamespaceService.kt`](https://github.com/ahoo-wang/cosky/blob/main/NamespaceService.kt)) provides additional management operations:

```kotlin
// List all registered namespaces
namespaceService.namespaces.subscribe { println(it) }

// Permanently delete a namespace and all its data
namespaceService.deleteNamespace("old-tenant").subscribe()

```

Runtime switching changes the thread-local `NamespacedContext` immediately, causing subsequent operations to target the new tenant's keyspace in Redis.

## Using the REST API for Namespace Operations

All tenant-aware endpoints reside under **`/v1/namespaces/{namespace}`**. The REST API defined in [`RequestPathPrefix.kt`](https://github.com/ahoo-wang/cosky/blob/main/RequestPathPrefix.kt) exposes the following operations:

- **List namespaces**: `GET /v1/namespaces` returns all registered tenants.
- **Create namespace**: `POST /v1/namespaces` with body `{ "namespace": "new-tenant" }`.
- **Delete namespace**: `DELETE /v1/namespaces/{namespace}` removes the tenant and all associated data.
- **Config management**: `GET/PUT/DELETE /v1/namespaces/{namespace}/configs/{configId}` handles tenant-scoped configuration.
- **Service discovery**: `GET /v1/namespaces/{namespace}/services` lists services within the tenant.

Controllers extract the namespace from the path variable and pass it to the service layer. For example, [`ServiceController.kt`](https://github.com/ahoo-wang/cosky/blob/main/ServiceController.kt) implements:

```kotlin
// ServiceController.kt (excerpt)
@GetMapping("/{namespace}/services")
fun getServices(@PathVariable namespace: String): Mono<List<String>> =
    discoveryService.getServices(namespace).collectList()

```

## Summary

- **CoSky namespace isolation** separates tenant data by prefixing Redis keys with a logical namespace identifier.
- **Configure** the default namespace via `spring.cloud.cosky.namespace` in [`application.yaml`](https://github.com/ahoo-wang/cosky/blob/main/application.yaml), processed by [`CoSkyAutoConfiguration.kt`](https://github.com/ahoo-wang/cosky/blob/main/CoSkyAutoConfiguration.kt).
- **Runtime switching** uses `NamespaceService.setNamespace()` to update the thread-local `NamespacedContext`.
- **REST endpoints** require the `{namespace}` path variable under `/v1/namespaces/{namespace}` for all tenant-scoped operations.
- **Source files**: [`CoSkyProperties.kt`](https://github.com/ahoo-wang/cosky/blob/main/CoSkyProperties.kt), [`CoSkyAutoConfiguration.kt`](https://github.com/ahoo-wang/cosky/blob/main/CoSkyAutoConfiguration.kt), [`NamespaceService.kt`](https://github.com/ahoo-wang/cosky/blob/main/NamespaceService.kt), [`RequestPathPrefix.kt`](https://github.com/ahoo-wang/cosky/blob/main/RequestPathPrefix.kt), [`ServiceController.kt`](https://github.com/ahoo-wang/cosky/blob/main/ServiceController.kt), and [`CoSkyConfigRefresher.kt`](https://github.com/ahoo-wang/cosky/blob/main/CoSkyConfigRefresher.kt) implement the isolation logic.

## Frequently Asked Questions

### What is the default namespace in CoSky?

If you do not specify `spring.cloud.cosky.namespace`, CoSky uses `Namespaced.DEFAULT` with the value `"cosky"`. This global default ensures backward compatibility while allowing explicit tenant configuration.

### Can I change the namespace after the application starts?

Yes. Inject `NamespaceService` and call `setNamespace(tenant)` to update the thread-local context. This switches the tenant scope for subsequent operations without restarting the application, enabling multi-tenant SaaS architectures.

### How does namespace isolation work in Redis?

CoSky prefixes every stored key with the namespace identifier. For example, configuration keys for namespace `my-company` follow the pattern `my-company:config:{configId}`. This logical separation prevents data leakage between tenants while using a single Redis database.

### Are namespaces created automatically?

Namespaces are created implicitly when first used, or explicitly via `POST /v1/namespaces`. The `NamespaceService` tracks registered namespaces in Redis, allowing administrators to list or delete tenants through the REST API or programmatically via `deleteNamespace()`.