Deployment
Local Development
Prerequisites
- .NET 10 SDK
- Docker and Docker Compose
Start all services
docker-compose up -d
This starts:
- MongoDB on port 27017
- Mongo Express (admin UI) on port 8081
- API on port 5069
- Frontend on port 5173
To start only the database services:
docker-compose up -d mongodb mongo-express
Configure API keys
Copy or edit appsettings.Development.json:
{
"Sync": {
"UpstreamApiKey": "your-upstream-api-key"
},
"ApiKeys": [
"dev-test-key-1"
]
}
Run the API
cd Api
dotnet run
The API starts on http://localhost:5069 (see Properties/launchSettings.json).
Test endpoints
Use the provided Api.http file (works with VS Code REST Client or JetBrains HTTP Client):
# Trigger sync
curl -X POST http://localhost:5069/api/internal/sync \
-H "X-API-KEY: dev-test-key-1"
# Fetch treatment groups
curl http://localhost:5069/api/v1/treatmentGroup \
-H "X-API-KEY: dev-test-key-1"
MongoDB Indexes
Indexes are created automatically on application startup via AppDbContext.EnsureIndexesAsync():
| Collection | Index | Type |
|---|---|---|
TreatmentGroups |
BusinessKey |
Unique |
TreatmentGroups |
Version |
Ascending |
ReimbursementGroups |
BusinessKey |
Unique |
ReimbursementGroups |
Version |
Ascending |
These indexes ensure:
- Upserts by
BusinessKeyare efficient - Queries with
?sinceVersion=Nare fast (version index)
Kubernetes Deployment
API Deployment
Standard ASP.NET Core deployment. Key environment variables:
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: nompd-secrets
key: mongodb-connection-string
- name: Sync__UpstreamApiKey
valueFrom:
secretKeyRef:
name: nompd-secrets
key: upstream-api-key
- name: ApiKeys__0
valueFrom:
secretKeyRef:
name: nompd-secrets
key: client-api-key-1
Sync CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: nompd-sync
spec:
schedule: "0 2 * * *" # Every night at 02:00
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 5
failedJobsHistoryLimit: 3
jobTemplate:
spec:
backoffLimit: 3
template:
spec:
containers:
- name: sync
image: curlimages/curl
command:
- curl
- -X POST
- -H "X-API-KEY: $(SYNC_API_KEY)"
- -f
- --retry 3
- --retry-delay 10
- https://nompd-api.internal/api/internal/sync
restartPolicy: OnFailure
envFrom:
- secretRef:
name: nompd-sync-secrets
Key settings:
concurrencyPolicy: Forbidprevents overlapping syncsbackoffLimit: 3retries failed jobscurl -fmakes curl return non-zero exit code on HTTP errors, so K8s knows the job failed
Health Checks
Consider adding a health check endpoint (not API key protected) for K8s liveness/readiness probes:
GET /health → 200 OK
Docker Build
The API Dockerfile uses a multi-stage build with layer caching for NuGet restore. Note that docker-compose.yaml sets context: ./Api, so paths are relative to the Api directory.
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY Api.csproj .
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app
FROM mcr.microsoft.com/dotnet/aspnet:10.0
WORKDIR /app
COPY --from=build /app .
EXPOSE 8080
ENV ASPNETCORE_URLS=http://+:8080
ENTRYPOINT ["dotnet", "Api.dll"]