You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Cosmo Router uses a convention-based directory structure to automatically discover and load Connect RPC services. This approach co-locates proto files with their GraphQL operations for easy management.
194
+
195
+
### Configuration
196
+
197
+
Configure the router to point to your root services directory using a storage provider:
198
+
199
+
```yaml config.yaml
200
+
connect_rpc:
201
+
enabled: true
202
+
server:
203
+
listen_addr: "0.0.0.0:8081"
204
+
services_provider_id: "fs-services"
205
+
206
+
storage_providers:
207
+
file_system:
208
+
- id: "fs-services"
209
+
path: "./services" # Root services directory
210
+
```
211
+
212
+
The router will recursively walk the `services` directory and automatically discover all proto files and their associated GraphQL operations.
213
+
214
+
### Recommended Structure
215
+
216
+
For organization purposes, we recommend keeping all services in a root `services` directory, with subdirectories for packages and individual services.
217
+
218
+
#### Single Service per Package
219
+
220
+
When you have one service per package, you can organize files directly in the package directory:
221
+
222
+
```
223
+
services/
224
+
└── employee.v1/ # Package directory
225
+
├── employee.proto # Proto definition
226
+
├── employee.proto.lock.json
227
+
├── GetEmployee.graphql # Operation files
228
+
├── UpdateEmployee.graphql
229
+
└── DeleteEmployee.graphql
230
+
```
231
+
232
+
Or with operations in a subdirectory:
233
+
234
+
```
235
+
services/
236
+
└── employee.v1/
237
+
├── employee.proto
238
+
├── employee.proto.lock.json
239
+
└── operations/
240
+
├── GetEmployee.graphql
241
+
├── UpdateEmployee.graphql
242
+
└── DeleteEmployee.graphql
243
+
```
244
+
245
+
#### Multiple Services per Package
246
+
247
+
When multiple services share the same proto package, organize them in service subdirectories:
248
+
249
+
```
250
+
services/
251
+
└── company.v1/ # Package directory
252
+
├── EmployeeService/ # First service
253
+
│ ├── employee.proto # package company.v1; service EmployeeService
254
+
│ ├── employee.proto.lock.json
255
+
│ └── operations/
256
+
│ ├── GetEmployee.graphql
257
+
│ └── UpdateEmployee.graphql
258
+
└── DepartmentService/ # Second service, same package
259
+
├── department.proto # package company.v1; service DepartmentService
260
+
├── department.proto.lock.json
261
+
└── operations/
262
+
├── GetDepartment.graphql
263
+
└── ListDepartments.graphql
264
+
```
265
+
266
+
### Flexible Organization
267
+
268
+
The router determines service identity by proto package declarations, not directory names. This gives you flexibility in organizing your files:
269
+
270
+
```
271
+
services/
272
+
├── hr-services/
273
+
│ ├── employee.proto # package company.v1; service EmployeeService
274
+
│ └── GetEmployee.graphql
275
+
└── admin-services/
276
+
├── department.proto # package company.v1; service DepartmentService
277
+
└── GetDepartment.graphql
278
+
```
279
+
280
+
<Note>
281
+
**Service Uniqueness**: The combination of proto package name and service name must be unique. For example, you can have multiple services with the same package name (e.g., `company.v1`) as long as they have different service names (`EmployeeService`, `DepartmentService`). The router uses the package + service combination to identify and route requests.
282
+
</Note>
283
+
284
+
### Discovery Rules
285
+
286
+
The router follows these rules when discovering services:
287
+
288
+
1. **Recursive Discovery**: The router recursively walks the services directory to find all `.proto` files
289
+
2. **Proto Association**: Each `.proto` file discovered becomes a service endpoint
290
+
3. **Operation Association**: All `.graphql` files in the same directory (or subdirectories) are associated with the nearest parent `.proto` file
291
+
4. **Nested Proto Limitation**: If a `.proto` file is found in a directory, any `.proto` files in subdirectories are **not** discovered (the parent proto takes precedence)
292
+
293
+
#### Example: Nested Proto Files
294
+
295
+
```
296
+
services/
297
+
└── employee.v1/
298
+
├── employee.proto # ✅ Discovered as a service
299
+
├── GetEmployee.graphql # ✅ Associated with employee.proto
300
+
└── nested/
301
+
├── other.proto # ❌ NOT discovered (parent proto found first)
302
+
└── UpdateEmployee.graphql # ✅ Still associated with employee.proto
303
+
```
304
+
305
+
<Warning>
306
+
**Avoid Nested Proto Files**: Do not place `.proto` files in subdirectories of a directory that already contains a `.proto` file. The nested proto files will not be discovered by the router.
307
+
</Warning>
308
+
309
+
### Best Practices
310
+
311
+
1. **Use Semantic Versioning**: Include version numbers in package names (e.g., `employee.v1`, `employee.v2`) to support API evolution
312
+
2. **Co-locate Operations**: Keep GraphQL operations close to their proto definitions for easier maintenance
313
+
3. **Consistent Naming**: Use clear, descriptive names for packages and services that reflect their purpose
314
+
4. **Lock File Management**: Always commit `.proto.lock.json` files to version control to maintain field number stability
315
+
184
316
## Observability
185
317
186
318
The Cosmo Router provides built-in [observability features](/router/metrics-and-monitoring) that work seamlessly with Connect Client. Because the Router translates RPC calls into GraphQL operations, you get detailed metrics and tracing for both layers.
0 commit comments