REST API
The REST API is a Python service that publicly serves enriched and transformed data over several endpoints.
Architecture
Section titled “Architecture”How It Works
Section titled “How It Works”The REST API serves NBA ELT pipeline data through multiple endpoints and includes three main components:
1. REST API
Section titled “1. REST API”Serves NBA data through RESTful endpoints covering teams, players, games, betting odds, and user predictions. All endpoints are publicly accessible without authentication.
2. Web Application
Section titled “2. Web Application”A frontend interface that allows users to:
- Create accounts and log in with username and password
- Place simulated bets on upcoming NBA games using scraped moneyline odds
- View historical betting performance and track accuracy, automatically updated after game results are processed
3. Admin Dashboard
Section titled “3. Admin Dashboard”A restricted interface for users with Admin role to manage project-wide settings and features.
The REST API uses JWT (JSON Web Token) for authentication and authorization for the Web App & Admin Dashboard components.
- The
/tokenendpoint is used when users attempt to log in. - After validating the user’s credentials, the API returns a JWT that is used for subsequent requests.
User information, including the password, is stored in the database. The password is securely hashed and combined with a random salt for enhanced security.
- This approach eliminates the need for third-party user data management
User Roles
Section titled “User Roles”- A role is associated with each user in the database.
- There are two types of roles:
- Admin: Users with the Admin role have access to the Admin UI and various management pages.
- Consumer: Users are given this role by default and gain access to login, access the betting Pages, and view their historical betting accuracy
A Helm chart for the application to run on Kubernetes is built but not currently used in production for cost-saving purposes.
It can be found in the helm/ directory of the repository and includes:
values.yamlfiles for dev and prod environments- HPA support for autoscaling
- Ingress functionality for routing traffic to the custom domain (
api.jyablonski.dev) - Template files for Deployment, Service, ConfigMap, Secret, and other K8s resources
Libraries
Section titled “Libraries”- FastAPI is the primary package driving the REST API development
- Pydantic enables type validation for request and response information in the endpoints
- Mangum turns the REST API into something that can be served on AWS Lambda
- python-jose is used for handling JWT for user authentication
- SQLAlchemy is used to provide ORM functionality for Postgres
Production
Section titled “Production”In production, the REST API is hosted on an AWS Lambda function, with a Lambda Function URL configured for access. It’s then hooked up to a CloudFront Distribution routed via Route 53 to a custom domain to serve the application over https://api.jyablonski.dev.
- This setup is highly cost-effective, as Lambda allows for thousands of invocations with minimal cost, unlike ECS or EKS, which require payment for EC2 instances.
- But, it introduces a few limitations:
- The app becomes stateless, which can lead to cold starts
- Monitoring metrics with Prometheus is not possible in the same way as with traditional server setups.
- Features like OpenID Connect-based authentication (e.g., “Sign-in with Google”) are much more difficult to implement and maintain context
All request logs are stored in AWS Cloudwatch, and traces are tracked via OpenTelemetry and sent over to Honeycomb where they can be monitored & alerted on.
CI / CD
Section titled “CI / CD”For continuous integration (CI), the entire test suite is run on every commit in a pull request using Docker.
- Because the primary backend Database is Postgres, this enables comprehensive & performant testing
After a PR is merged, the continuous deployment (CD) pipeline performs the following steps:
- Builds a
.ZIPbundle containing the server’s source code and dependencies. - Stores the
.ZIPbundle in S3. - Updates the Lambda function with the new bundle.