Node.js (TypeScript) GraphQL API that integrates with the Weatherstack API to manage properties and their real-time weather data.
framework: Fastify architecure graphQL rest endpoint DB PostgreSQL ORM : typeorm GraphQL using mercurius Docker prettier, eslint Infrastructure as a code with AWS CDK tests with jest
The architectural goal was to build a clean, highly testable structure optimized for Test-Driven Development (TDD) and future extensibility, while maintaining a lightweight footprint:
- Repository Pattern: Isolates the Data Access Layer (DAL), making database operations easily mockable and decoupled from business logic.
- Service Layer / Use Case Pattern: Encapsulates the core business logic, ensuring controllers/resolvers remain thin.
- Adapter / Facade Pattern: Standardizes communication with the 3rd-party Weatherstack API, shielding the internal system from external contract changes.
- Dependency Injection (DI): Facilitates loose coupling and straightforward testing by injecting dependencies (like databases and API clients) rather than hardcoding them.
- In-Memory Caching: External Weatherstack API requests are securely cached (using an LRU strategy) based on the unique combination of city and state. Data is retained in memory with a 20-minute Time-To-Live (TTL) to drastically reduce latency and conserve API quotas.
- High-Performance Framework: Utilizes Fastify under the hood (via Mercurius) to handle HTTP/GraphQL requests with maximum throughput and minimal overhead.
- Database Indexing:
- An index is applied to the
statecolumn, accelerating high-level geographic filtering before narrowing down by city or zip code. - An index is applied to the
createdAtcolumn to optimize the performance of default chronological sorting.
- An index is applied to the
- Modern Runtime: Leverages the latest stable Node.js LTS version for built-in performance.
- GraphQL API: Strongly typed schema with structured
Weather,Astro, andAirQualitydata. - Real-time Integration: Fetches live weather data from Weatherstack for any property created.
- Persistent Storage: PostgreSQL with TypeORM migrations for schema management.
- Advanced Querying: Support for filtering by City, State, and Zip Code, plus sorting by creation date.
- Resilience & Backoff: Outbound exponential backoff retry logic for Weatherstack API rate limits (429) and transient failures (615).
- Caching: Memory-safe LRU caching (200 entries, 20-min TTL) to protect against memory leaks and reduce external API costs.
- Robustness: Full E2E and Unit test coverage with Jest.
- Node.js 20+
- Docker & Docker Compose
- A Weatherstack API Key (Get one here)
Create a src/.env file with the following variables:
WEATHER_API_KEY=your_api_key_here
WEATHER_API_URL=https://api.weatherstack.com/
DB_HOST=db
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_NAME=propertyTo start the application and database is via Docker Compose:
docker-compose up --buildThe API will be available at http://localhost:8080/graphql and the GraphiQL playground at http://localhost:8080/graphiql.
npm install
npm run build
npm run devmutation {
createProperty(city: "New York", street: "5th Ave", state: "NY", zipCode: "10001") {
id
city
weather {
temperature
weatherDescriptions
astro {
sunrise
}
}
}
}query {
properties(sortBy: "createdAt", order: "DESC", state: "NY") {
city
zipCode
createdAt
weather {
temperature
}
}
}Run the full test suite (Unit + E2E):
npm testWe provide utility scripts to quickly populate the database with property data across 30 different USA locations.
Includes a 3-second delay between requests to stay within Weatherstack's free tier rate limits.
chmod +x scripts/run_usa_queries.sh
./scripts/run_usa_queries.shNo delays. Use this if you have a Professional or higher Weatherstack plan.
chmod +x scripts/run_usa_queries_weather_api_premium.sh
./scripts/run_usa_queries_weather_api_premium- Protocol Considerations (HTTP vs. HTTPS): While HTTPS is available on most Weatherstack plans, historically the free tier required HTTP. Always verify protocol support for your specific subscription tier.
- Consistent Naming Conventions: Every property's weather data is defined via interfaces with strict naming conventions mapped to match the GraphQL schema standards from snake_case to CamelCase.
- Rate Limiting & Throttling: Currently, there is no request throttling. Implementing IP-based rate limiting could prevent issues like duplicate record creation from rapid double-clicks.
- Duplicate Records: The same property can currently be added multiple times as there is no highly specific identifier (like an apartment unit number) to enforce uniqueness. A business rule could be added to prevent exact duplicates.
- Location Precision: The Weatherstack API resolves location data at the city level. If future requirements demand hyper-local precision (e.g., precise street-level coordinates), the weather provider will need to be re-evaluated or replaced.