A backend API built with NestJS, TypeORM, and PostgreSQL.
- Node.js (v20 or later)
- pnpm (v8 or later)
- Docker and Docker Compose (for containerized deployment)
- Clone the repository:
git clone <repository-url>
cd teddy-api- Install dependencies:
pnpm install- Create a
.envfile in the root directory with the following content (adjust as needed):
# Application port
PORT=3000
# Environment (development, test, production)
NODE_ENV=development
# Main database host (use 'db' when running with Docker)
DB_HOST=db
# Main database port
DB_PORT=5432
# Database username
DB_USER=teddy_user
# Database password
DB_PASSWORD=teddy_password
# Main database name
DB_NAME=teddy_db
The easiest way to run the application is using Docker Compose, which will set up both the API and PostgreSQL database:
-
Make sure Docker and Docker Compose are installed and running.
-
Build and start the containers:
docker-compose up -dThis will:
- Start a PostgreSQL database container
- Build and start the API container
- Connect the API to the database
- Expose the API on port 3000
Here's a snippet of the docker-compose.yml configuration:
services:
db:
image: postgres:latest
env_file:
- .env
environment:
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_DB=${DB_NAME}
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
interval: 5s
timeout: 5s
retries: 5
api:
build:
context: .
dockerfile: Dockerfile
env_file:
- .env
ports:
- "3000:3000"
depends_on:
db:
condition: service_healthy
command: pnpm start:prodThe api service depends on the db service and will only start once the database is healthy. The API service uses DB_HOST=db to connect to the database container.
- To stop the containers:
docker-compose down- To view logs:
docker-compose logs -f apiIf you prefer to run the application locally for development:
- Update the
.envfile to use localhost for the database:
DB_HOST=localhost
- Start a PostgreSQL instance (either locally or using Docker):
docker-compose up -d db- Run the application in development mode:
pnpm start:devThe API will be available at http://localhost:3000 with hot-reload enabled.
The application uses TypeORM to connect to PostgreSQL. The connection is configured using environment variables:
DB_HOST: Database host (default: 'db')DB_PORT: Database port (default: 5432)DB_USER: Database username (default: 'teddy_user')DB_PASSWORD: Database password (default: 'teddy_password')DB_NAME: Database name (default: 'teddy_db')
When running with Docker, these same DB_* variables are automatically mapped to the PostgreSQL-specific environment variables (POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB) in the docker-compose.yml file, eliminating the need for duplicate configuration.
In development mode, the database schema is automatically synchronized with the entity definitions.
# Start the application in development mode with hot-reload
pnpm start:dev
# Start the application in debug mode
pnpm start:debug# Run tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Run tests with coverage
pnpm test:cov# Run ESLint
pnpm lint
# Format code with Prettier
pnpm format# Build the application
pnpm build
# Check TypeScript types without emitting files
pnpm exec tsc --noEmit
# Start the built application
pnpm start:prodThe Teddy API follows a modular architecture based on NestJS best practices:
- Framework: NestJS - A progressive Node.js framework for building efficient and scalable server-side applications
- Database: PostgreSQL - A powerful, open-source object-relational database system
- ORM: TypeORM - An ORM that can run in Node.js and supports both Active Record and Data Mapper patterns
- Validation: class-validator - Decorator-based property validation for classes
- API Documentation: Swagger/OpenAPI - Interactive API documentation and exploration tool
The project follows a vertical module-based structure:
src/
├── config/ # Application configuration
├── modules/ # Feature modules
│ └── clients/ # Example module for clients
│ ├── controller/ # HTTP request handlers
│ ├── service/ # Business logic
│ ├── dto/ # Data Transfer Objects
│ ├── entity/ # Database entities
│ ├── repository/ # Data access layer
│ └── use-case/ # (Optional) Use cases
├── app.module.ts # Main application module
└── main.ts # Application entry point
Each module is self-contained with its own controllers, services, entities, and repositories, promoting separation of concerns and maintainability.
The Teddy API includes comprehensive API documentation using Swagger/OpenAPI. This documentation provides detailed information about all available endpoints, including:
- Available routes and HTTP methods
- Request parameters and body schemas
- Response schemas and status codes
- Example values for testing
To access the Swagger documentation:
- Start the application (using any of the methods described above)
- Open your browser and navigate to http://localhost:3000/api
The interactive Swagger UI allows you to:
- Explore all available endpoints
- View detailed request/response information
- Test endpoints directly from the browser
- Understand the data models used by the API
All endpoints in the Clients module are fully documented with detailed information about input parameters and response formats, including possible error responses.
The Teddy API includes comprehensive observability features using Prometheus for metrics, Loki for logs, and Grafana for visualization.
When running the application with Docker Compose, the following services are available:
- Grafana: http://localhost:3001 (login with admin/admin)
- Prometheus: http://localhost:9090
- Loki: http://localhost:3100
The Grafana dashboard provides a unified view of metrics and logs:
- Login: Use the credentials
admin/adminto access the Grafana dashboard - Default Dashboard: A pre-configured dashboard called "Teddy API Dashboard" is available
- Metrics Panels: View HTTP request counts, response times, and error rates
- Logs Panel: View application logs in real-time
The API exposes metrics at the /metrics endpoint, which Prometheus scrapes every 15 seconds. Key metrics include:
- HTTP Request Counts: Total number of requests by method and endpoint
- HTTP Request Duration: Response time histograms by method and endpoint
- Error Rates: Count of HTTP errors by status code
- In-Progress Requests: Gauge of currently active requests
To query these metrics directly, access the Prometheus UI at http://localhost:9090.
Application logs are collected by Loki and can be queried through Grafana. The logs include:
- HTTP Request/Response Details: Method, path, status code, and duration
- Error Information: Detailed error messages and stack traces
- Application Events: Service startup, configuration changes, etc.
The API includes a health check endpoint at /health that monitors:
- Database Connectivity: Checks if the PostgreSQL database is accessible
- API Status: Verifies that the API is functioning correctly
The Teddy API is designed to be deployed on AWS with the following architecture:
-
API Gateway: Routes all incoming HTTP requests to the API service, providing a single entry point with features like request throttling, authentication, and monitoring.
-
ECS/Fargate: Hosts the containerized API application, allowing for scalable, serverless container management without the need to provision or manage servers.
-
RDS (PostgreSQL): Managed relational database service for PostgreSQL, providing automated backups, patching, and high availability.
-
RabbitMQ: Messaging service for scalability, used to process asynchronous tasks (e.g., sending emails or notifications after creating a client), enabling decoupling and improved resilience.
-
CloudWatch: Comprehensive monitoring solution for logs, metrics, and alarms. The application is configured to export:
- Metrics: All Prometheus metrics are exported to CloudWatch Metrics
- Logs: Application logs are sent to CloudWatch Logs
- Alarms: Configured for error rates, response times, and resource utilization
- Dashboards: Pre-configured CloudWatch dashboards for monitoring application health
-
Secrets Manager: Securely stores and manages sensitive configuration values like database credentials and API keys, with automatic rotation capabilities.
- VPC: Provides network isolation for the application components, with private subnets for the database and application containers, and public subnets for the load balancer.
This architecture ensures scalability, security, and reliability for the Teddy API in a production environment.