Tier 2: Do These Next (Operational Quality)
4. Observability — Prometheus + Grafana
Now Grafana makes sense, but only as a visualization layer on top of metrics. Here's the stack:
Prometheus: Instrument your Go backend with promhttp. Track request latency, LLM call duration, error rates, queue depth, active users.
Grafana: Dashboard over Prometheus. Lets you see at a glance: How long do LLM calls take? How many users are generating per hour? What's the error rate?
Structured logging: Replace log.Printf with slog (stdlib in Go 1.21+). Output JSON logs. Ship to Grafana Loki if you want searchable logs.
Instrument these specific things first:
LLM call latency and success rate (per endpoint)
Queue depth and job completion time
API request latency per route
Active concurrent users
5. Redis for Rate Limiting and Caching
You already need Redis for the job queue (Tier 1). Also use it for:
Rate limiting — Replace your in-memory RateLimiter with a Redis-backed sliding window. Works across multiple backend instances.
Caching — Cache LLM results keyed by hash(resume + job_description). If a user re-optimizes the same inputs, return the cached result instantly.
6. Object Storage for PDFs — S3/MinIO
Instead of writing .tex and PDF files to the local filesystem and deleting them, store them in object storage:
Use MinIO in Docker for local dev (S3-compatible).
Use S3 or GCS in production.
Store generated PDFs with a TTL or permanently if tied to an application record in Postgres.
This enables the "view my past applications" feature and decouples file storage from the backend process.
////
This is Cursor
Tier 2: Do These Next (Operational Quality)
4. Observability — Prometheus + Grafana
Now Grafana makes sense, but only as a visualization layer on top of metrics. Here's the stack:
Prometheus: Instrument your Go backend with promhttp. Track request latency, LLM call duration, error rates, queue depth, active users.
Grafana: Dashboard over Prometheus. Lets you see at a glance: How long do LLM calls take? How many users are generating per hour? What's the error rate?
Structured logging: Replace log.Printf with slog (stdlib in Go 1.21+). Output JSON logs. Ship to Grafana Loki if you want searchable logs.
Instrument these specific things first:
LLM call latency and success rate (per endpoint)
Queue depth and job completion time
API request latency per route
Active concurrent users
5. Redis for Rate Limiting and Caching
You already need Redis for the job queue (Tier 1). Also use it for:
Rate limiting — Replace your in-memory RateLimiter with a Redis-backed sliding window. Works across multiple backend instances.
Caching — Cache LLM results keyed by hash(resume + job_description). If a user re-optimizes the same inputs, return the cached result instantly.
6. Object Storage for PDFs — S3/MinIO
Instead of writing .tex and PDF files to the local filesystem and deleting them, store them in object storage:
Use MinIO in Docker for local dev (S3-compatible).
Use S3 or GCS in production.
Store generated PDFs with a TTL or permanently if tied to an application record in Postgres.
This enables the "view my past applications" feature and decouples file storage from the backend process.
////
This is Cursor