Shorty is an fully containerized URL shortener backend built with Go. It's designed to be fast, scalable, and maintainable. It features authentication & authorization, analytics, caching and message broking.
- Secure User Management: JWT-based authentication and authorization for multi-tenant usage.
- Custom Short URLs: Users can create personalized, branded short links.
- Blazing-Fast Redirects: Sub-millisecond response times for shortened URLs, with in-memory caching with Redis.
- Asynchronous, High-Throughput Click Analytics: Redirect analytics are processed asynchronously using RabbitMQ, ensuring the user-facing redirect path is never blocked.
- Strict Input Validation: All request payloads are validated with
go-playground/validatorto ensure data integrity and prevent malformed inputs. - Clean, Vertical Slice Architecture: The codebase is organized by feature, making it highly modular, easy to test, and simple for teams to collaborate on.
- API Rate Limiting: Protects the API from abuse and ensures service stability.
- Structured, Production-Ready Logging: Uses
zerologfor high-performance, structured (JSON) logging. - Developer-First Experience: Auto-generated interactive API documentation via Swagger and a single-command setup with Docker or make.
- Unit Tests: Each key part of the project has unit tests to ensure they comply with business requirements throughout the development
- Future-Proof: The APIs are designed with an admin dashboard in mind, making it simple, fast, and efficient to set up a fully functional management interface.
The entire project is containerized for a seamless, one-command setup.
-
Clone the repository:
git clone https://github.com/Kalmera74/Shorty cd Shorty -
Bring the entire stack online:
docker-compose up
This command will build the Go application image and start containers for the API, the analytics worker, PostgreSQL, Redis, and RabbitMQ.
-
Explore the API: Once the containers are running, the interactive Swagger API documentation is available at: http://localhost:8080/swagger
This project was designed with performance, scalability, and maintainability in mind. Every technology and pattern was chosen to solve a specific problem.
| Category | Technology |
|---|---|
| Core Backend | Go, Fiber (High-Performance Web Framework), Gorm (ORM), Validator (go-playground/validator) |
| Data & Infrastructure | PostgreSQL (Primary Datastore), Redis (Caching), RabbitMQ (Message Broker) |
| DevOps & Tooling | Docker & Docker Compose (Containerization), GitHub Actions (CI/CD), Makefile (Build Automation) |
| Observability & Docs | Zerolog (Structured Logging), Swagger/OpenAPI (API Documentation) |
The system is split into two primary workflows: the read-optimized redirect path and the write-intensive analytics path.
-
URL Redirect (The Critical Path):
- A request for a short URL hits the API.
- The service first checks Redis using a cache-aside pattern. A cache hit results in an immediate redirect, avoiding any database interaction.
- On a cache miss, the service queries PostgreSQL, populates the Redis cache for future requests, and then redirects.
- Crucially, a "click" event is published to RabbitMQ without waiting for a response. The redirect is never blocked by analytics processing.
-
Analytics Processing (The Decoupled Path):
- The
analytics-workeris a separate, dedicated Go service. - It consumes messages from the RabbitMQ queue in the background.
- This worker is solely responsible for parsing click data and persisting it to PostgreSQL. This decoupling means the two services can be scaled independently.
- The
-
Clean Architecture with Vertical Slices: The project structure under
internal/featuresis deliberate. Each feature (e.g.,user,shortener) is a self-contained module. This promotes high cohesion and low coupling, making the codebase easy to navigate, test, and extend, and allows development teams to work on features in parallel with minimal friction. -
Validation First: All request objects are validated with
go-playground/validatorto ensure strict type and format guarantees at the API boundary. This prevents invalid data from propagating into the system and reduces runtime errors. -
Event-Driven & Asynchronous: By using RabbitMQ, we decouple the critical, user-facing redirect logic from the non-critical, background analytics work. This drastically improves perceived performance and resilience. The redirect service remains lightweight and fast, even under heavy load.
-
Stateless for Scalability: Using JWTs for authentication means the application is stateless. Any API instance can serve any authenticated request. This is crucial for horizontal scalability, allowing us to run multiple instances behind a load balancer without needing sticky sessions.
-
Role-Based Authorization (RBAC): Shorty uses simple, string-based roles (e.g.,
admin,user) for authorization. This lightweight approach keeps the system easy to manage while still allowing future extension to fine-grained policies if needed. -
API Rate Limiting: Rate limiting is applied at the API gateway level to prevent abuse, protect from brute-force attacks, and maintain service stability under high load.
-
Structured Logging: Logging is done with
zerolog, producing structured JSON logs. This enables seamless integration with monitoring/observability tools like ELK or Grafana Loki while remaining high-performance in production environments. -
Configuration Management: All configuration (database URLs, JWT secrets, etc.) is managed via environment variables and loaded with
Godotenv. This follows the twelve-factor app methodology, ensuring no secrets are hardcoded and the application is portable across environments.
├── cmd/ # Entrypoints for our binaries
│ ├── api/ # Main API application
│ └── analytics-worker/ # Background worker for processing clicks
├── internal/ # Private application code, not for export
│ ├── apperrors/ # Custom application-specific errors
│ ├── features/ # Core business logic, organized by feature (Vertical Slices)
│ │ ├── shortener/ # All code related to URL shortening
│ │ |── user/ # All code related to user management
│ ├── middleware/ # Shared HTTP middleware (e.g., auth)
│ └── ...
├── pkg/ # Public library code, shareable with other projects
│ ├── auth/ # JWT generation and validation logic
│ ├── cache/ # Redis client wrapper
│ └── ...
├── docs/ # Swagger/OpenAPI documentation files
├── Dockerfile # Defines the Go application container
└── docker-compose.yml # Defines and orchestrates all services