~/projects/redyx
$ info

Redyx

An anonymous, community-driven discussion platform inspired by Reddit, built from scratch as a distributed system. 12 Go microservices communicating over gRPC, fronted by Envoy, with Kafka for async workflows, consistent-hashing-based database sharding, and full Kubernetes deployment with observability.

$ stack
GogRPCEnvoy+12
$ links
Redyx project screenshot
$ cat README.md | render

Redyx -- Anonymous Discussion Platform

Redyx is an anonymous, community-driven discussion platform inspired by Reddit, built from scratch as a distributed microservice system. Users create communities, post content (text, links, media), comment in nested threads, and vote on everything -- all under pseudonymous usernames. No real names, no exposed emails, no stored IP addresses.

The backend consists of 12 Go microservices communicating over gRPC, fronted by an Envoy API gateway that translates REST/JSON from the Astro + Svelte frontend. Asynchronous workflows flow through Apache Kafka. Fully containerized and deployable on Kubernetes with a complete observability stack.


Architecture

1+------------------+
2 | Cloudflare CDN |
3 +--------+---------+
4 |
5 +--------v---------+
6 | Astro Frontend | (SSR + Svelte Islands)
7 +--------+---------+
8 | REST/JSON
9 +--------v---------+
10 | Envoy Gateway |
11 | - REST -> gRPC |
12 | - Rate limiting |
13 | - JWT validation|
14 +--------+---------+
15 | gRPC (internal)
16 +------------------+------------------+
17 | | | | |
18 +----v---+ +---v----+ +v------+ +v------+ +v--------+
19 | Auth | | User | | Post | | Vote | | Comment |
20 | Service| | Service| | Svc | | Svc | | Service |
21 +----+---+ +---+----+ +---+---+ +---+---+ +----+----+
22 | | | | |
23 +----v---+ +---v----+ +--v----+ +-v------+ +---v-----+
24 |Postgres| |Postgres| |Postgres| | Redis | | ScyllaDB|
25 | (auth) | | (user) | |(shard) | | +Kafka | | |
26 +--------+ +--------+ +-------+ +--------+ +---------+
27
28 +------------------+------------------+------------------+
29 | | | | | |
30+----v-----+ +v------+ +v--------+ +------v-------+ +--------v-------+
31| Community| | Search| | Media | | Notification | | Moderation/Spam|
32| Service | | Svc | | Service | | Service | | Services |
33+----+-----+ +---+---+ +----+----+ +------+-------+ +--------+-------+
34 | | | | |
35+----v---+ +----v-----+ +--v-----+ +----v----+ +-----v----+
36|Postgres| |Meilisearch| | MinIO | | Redis | | Postgres |
37|(commty)| +----------+ | (S3) | | +Kafka | | +Redis |
38+--------+ +--------+ | +PG | | +Kafka |
39 +---------+ +----------+

Tech Stack

LayerTechnologyPurpose
FrontendAstro (SSR) + Svelte (Islands)Content-driven pages with minimal JS; interactive components hydrate as Svelte islands
API GatewayEnvoy ProxyREST-to-gRPC transcoding, rate limiting, CORS, load balancing, WebSocket upgrades
BackendGo (Golang)All 12 microservices; high concurrency, strong gRPC ecosystem
Service CommgRPC + Protocol BuffersType-safe, binary protocol for inter-service calls; 15 .proto definitions
Message QueueApache KafkaEvent-driven workflows: vote processing, search indexing, notifications, spam analysis
CacheRedisSession store, vote counts, rate limiting, hot feeds, OTP codes, WebSocket registry
Primary DBPostgreSQL 16ACID-compliant relational storage across 5 instances (one sharded)
Comment StoreScyllaDB 6.2High-throughput wide-column store for nested comment trees
SearchMeilisearch v1.12Full-text search with typo tolerance, ranked by relevance + recency + score
Object StorageMinIO (S3-compatible)Image/video uploads, thumbnails; production uses AWS S3 + CloudFront
OrchestrationKubernetes (kind for local)Helm charts, HPA, namespace isolation, NGINX Ingress
MonitoringPrometheus + GrafanaMetrics collection via /metrics endpoints; per-service dashboards
LoggingLoki + PromtailCentralized structured JSON log aggregation, queryable through Grafana
TracingOpenTelemetry + JaegerDistributed request tracing across all microservices
Auth TokensJWT (access 15m + refresh 7d)Stateless authentication with short-lived access and long-lived refresh tokens
Password HashingArgon2idMemory-hard, GPU-resistant hashing (RFC 9106 parameters)

Services Overview

The most architecturally significant service -- handles post CRUD, feed generation, and ranking with database sharding via consistent hashing.

  • Post types: text (markdown), link, media
  • Anonymous posting (visible only to moderators)
  • Feed generation: community feed (single-shard), home feed (cross-shard fan-out), saved posts
  • Ranking algorithms: Hot (Lemmy algorithm), New, Top (time-filtered), Rising (velocity-based)
  • Consistent hashing: community_id maps to shard via hash ring with 40 virtual nodes per shard
  • Pre-publish spam and moderation checks (synchronous gRPC)
  • Kafka events: PostCreated, PostUpdated, PostDeleted consumed by Search, Notification, Spam

Database Architecture

The system uses 9 data stores across 5 technologies:

PostgreSQL (5 instances): pg-auth (credentials), pg-user (profiles/karma), pg-community (communities/memberships), pg-post (sharded by community_id), pg-platform (moderation/notifications/media metadata).

ScyllaDB (1 cluster): All comments, partitioned by post_id, clustered by materialized path.

Redis (1 instance, 12 logical databases): Each service gets a dedicated db (db0-db11) -- OTP codes, vote state, karma cache, feed cache, WebSocket registry, dedup hashes, and more.

Meilisearch (1 instance): Full-text search index for posts and communities.

MinIO / S3 (1 bucket): Object storage for uploads, thumbnails, and community banners.


Post Sharding with Consistent Hashing

The Post Service implements application-level database sharding using consistent hashing:

  1. Each community_id is hashed onto a ring using serialx/hashring
  2. The ring has 40 virtual nodes per physical shard for even distribution
  3. All posts for a community land on the same shard
  4. Community feed queries hit a single shard (no cross-shard joins)
  5. Home feed queries fan out to all shards in parallel

Adding a new shard: consistent hashing ensures only ~1/N of data migrates. Identify affected community_id values, background-migrate, flip routing, clean up.

Current deployment: 2 shards (posts_shard_0, posts_shard_1), each in its own PostgreSQL database.


Async Event Flows (Kafka)

1VoteCreated ->
2 Post Service: update post score
3 Comment Service: update comment score
4 User Service: update karma
5 Spam Service: vote manipulation detection
6
7PostCreated ->
8 Search Service: index in Meilisearch
9 Notification Service: notify community followers
10 Spam Service: analyze for spam patterns
11
12PostRemoved ->
13 Post Service: mark as removed
14 Notification Service: notify the author
15 Search Service: remove from index

Security and Privacy

  • Anonymity by design: Users identified only by username; no real name, phone, or location
  • Argon2id: RFC 9106 parameters (64 MiB memory, GPU-resistant)
  • JWT: Short-lived access tokens (15 min) with long-lived refresh tokens (7 days)
  • No IP storage: IPs hashed with SHA-256 + salt for abuse detection (24h TTL in Redis)
  • TLS everywhere: Envoy terminates external TLS; internal mTLS via Istio (optional)
  • Parameterized queries: No string concatenation in SQL
  • Account deletion: True PII purge; posts become [deleted], vote records anonymized
  • Constant-time comparison: subtle.ConstantTimeCompare for password verification

Observability

  • Prometheus: Scrapes /metrics from each service via go-grpc-prometheus interceptors
  • Grafana: Per-service dashboards with Prometheus, Loki, and Jaeger data sources
  • Loki + Promtail: Centralized structured JSON log aggregation
  • Jaeger: Distributed tracing via OpenTelemetry SDK, trace context propagated across gRPC calls
  • Alerting: Error rate spikes, P99 latency thresholds, pod restarts, Kafka consumer lag

Deployment

Docker Compose (Local Development)

$
make docker-up          # Start all services
make docker-logs        # Tail logs
make docker-down        # Stop everything

Kubernetes (kind)

$
make k8s-up             # Full deployment: cluster + ingress + storage + data + monitoring + app
make k8s-status         # Show cluster status
make k8s-down           # Tear down everything

Namespaces: redyx-app (12 microservices + Envoy), redyx-data (PostgreSQL, Redis, ScyllaDB, Kafka, Meilisearch, MinIO), redyx-monitoring (Prometheus, Grafana, Loki, Jaeger).

Features: Helm chart, HPA per service, gRPC health probes, ConfigMaps/Secrets, NGINX Ingress Controller.


Screenshots


Project Structure

1redyx/
2|-- cmd/ # Service entry points (main.go per service)
3| |-- auth/, comment/, community/, media/, moderation/
4| |-- notification/, post/, search/, spam/, user/, vote/
5|
6|-- internal/ # Service implementations
7| |-- auth/ # Hasher, JWT, OAuth, OTP, email
8| |-- comment/ # ScyllaDB, materialized path, Wilson score
9| |-- community/ # CRUD, cache
10| |-- media/ # S3, thumbnails
11| |-- moderation/ # Mod actions, store
12| |-- notification/ # WebSocket hub, Kafka consumer
13| |-- post/ # Shard router, ranking, cache, Kafka
14| |-- search/ # Meilisearch client, Kafka indexer
15| |-- spam/ # Blocklist, dedup, Kafka consumer
16| |-- user/ # Profiles, karma
17| |-- vote/ # Redis Lua scripts, Kafka producer/consumer
18| |-- platform/ # Shared libraries (JWT, config, DB, errors,
19| # middleware, observability, pagination,
20| # rate limiting, Redis)
21|
22|-- proto/redyx/ # 15 Protocol Buffer definitions
23|-- gen/ # Generated Go code from protobuf
24|-- migrations/ # SQL migrations per database
25|-- deploy/
26| |-- docker/ # Multi-stage Dockerfile, init-databases.sql
27| |-- envoy/ # Envoy config (REST->gRPC transcoding)
28| |-- k8s/ # kind config, storage, data, monitoring,
29| # ingress, Helm chart
30|-- web/ # Astro + Svelte frontend
31|-- docker-compose.yml
32|-- Makefile