{"slug": "how-i-built-a-visa-tracker-with-django-aurora-postgresql-and-react", "title": "How I Built a Visa Tracker with Django, Aurora PostgreSQL, and react", "summary": "A developer built VisaTrack, an AI-powered visa document tracker using Django, Aurora PostgreSQL, and React. The project required a custom Django database backend to handle IAM authentication, as the Aurora cluster's Express Configuration locked password authentication. The backend generates short-lived IAM tokens via boto3 for each connection.", "body_md": "Visa applications are stressful. You have dozens of documents to collect, country-specific requirements to meet, and strict deadlines to hit — all with zero visibility into where you actually stand. I built VisaTrack to fix that: an AI-powered document tracker that generates your required checklist automatically, lets you track progress, upload files, and get guidance from an AI advisor.\n\nI built it for the H0 — Hack the Zero Stack with Vercel v0 & AWS Databases hackathon. Here's how it came together.\n\nThe Stack\n\nLayerTechnologyFrontendReact, TypeScript, Tailwind CSSBackendDjango, Django REST FrameworkDatabaseAmazon Aurora PostgreSQL (Serverless v2)AIGoogle Gemini 2.5 FlashFrontend HostingVercelBackend HostingRailwayCloudAWS (eu-north-1)\n\nThe idea was simple: user picks a destination country and visa purpose, Gemini generates the document checklist, and the user tracks their progress in a clean UI. Pro users get access to a conversational AI advisor that answers questions specific to their application.\n\nWhy Aurora PostgreSQL\n\nThe hackathon required one of three AWS databases: Aurora PostgreSQL, Aurora DSQL, or DynamoDB.\n\nDynamoDB was out immediately — it's a NoSQL key-value store and Django's ORM is relational by design. You'd have to throw out migrations, the admin panel, and most of DRF's generic views.\n\nAurora DSQL looked promising until I read the docs. It's a distributed SQL engine launched in late 2024 and still in preview. Critical limitation: no foreign keys, no sequences. Django's auto-increment primary keys rely on sequences, so models break before you even run your first migration.\n\nAurora PostgreSQL was the clear choice. It's fully compatible with PostgreSQL, which means Django's ORM, migrations, and Django Admin all work out of the box. The serverless v2 configuration auto-scales between 0 and 4 ACUs based on demand — perfect for a hackathon project where traffic is unpredictable.\n\nThe Hardest Part: IAM Authentication\n\nThis is where things got interesting.\n\nI created the Aurora cluster using AWS's \"Express Configuration\" — a one-click setup that spins up a serverless cluster in seconds. What I didn't realize was that express config automatically enables Internet Access Gateway and IAM Database Authentication, and those two features are permanently locked together. You cannot use password authentication when the Internet Access Gateway is enabled.\n\nSo when I tried connecting Django to Aurora with a standard DATABASE_URL, every connection attempt failed with:\n\nFATAL: PAM authentication failed for user \"postgres\"\n\nThe solution was to build a custom Django database backend that generates short-lived IAM tokens on every connection using boto3 instead of using a static password.\n\nHere's the backend I wrote at config/db_backends/iam_auth/base.py:\n\npythonimport boto3\n\nimport os\n\nfrom django.db.backends.postgresql import base\n\nclass DatabaseWrapper(base.DatabaseWrapper):\n\ndef get_connection_params(self):\n\nparams = super().get_connection_params()\n\nclient = boto3.client(\n\n'rds',\n\nregion_name='eu-north-1',\n\naws_access_key_id=os.environ.get('AWS_ACCESS_KEY_ID'),\n\naws_secret_access_key=os.environ.get('AWS_SECRET_ACCESS_KEY'),\n\n)\n\ntoken = client.generate_db_auth_token(\n\nDBHostname=params['host'],\n\nPort=int(params['port']),\n\nDBUsername=params['user']\n\n)\n\nparams['password'] = token\n\nparams['sslmode'] = 'require'\n\nreturn params\n\nAnd the Django settings:\n\npythonDATABASES = {\n\n'default': {\n\n'ENGINE': 'config.db_backends.iam_auth',\n\n'NAME': 'postgres',\n\n'USER': 'postgres',\n\n'HOST': 'visatrack-db.cluster-xxxx.eu-north-1.rds.amazonaws.com',\n\n'PORT': '5432',\n\n'CONN_MAX_AGE': 0, # important — forces a fresh token on every connection\n\n}\n\n}\n\nDjango database backends are expected to be Python packages with a base.py file — that's why the path is iam_auth/base.py and not just iam_auth.py. The ENGINE string tells Django where to find the DatabaseWrapper class.\n\nCONN_MAX_AGE must be 0 here. IAM tokens expire after 15 minutes, so persistent connections would eventually fail with an expired token. Setting it to 0 forces Django to generate a fresh token on every request.\n\nOn the Railway side, I set three environment variables:\n\nAWS_ACCESS_KEY_ID=...\n\nAWS_SECRET_ACCESS_KEY=...\n\nAWS_DEFAULT_REGION=eu-north-1\n\nThe IAM user has AmazonRDSFullAccess and an inline policy allowing rds-db:connect. Once that was in place, migrations ran cleanly and the app was live.\n\nFrontend on Vercel\n\nThe React frontend was straightforward to deploy on Vercel. Connect the repo, set the root directory to Frontend/, and Vercel handles the rest. The only configuration needed was the backend API URL as an environment variable:\n\nVITE_API_URL=[https://application-tracker-production-3af2.up.railway.app](https://application-tracker-production-3af2.up.railway.app)\n\nVercel's preview deployments were genuinely useful during development — every push to a branch got its own URL for testing without touching production.\n\nThe AI Layer\n\nEvery time a user creates a new application, the backend calls Gemini 2.5 Flash with a prompt that includes the destination country and visa purpose. Gemini returns a JSON array of required documents — each with a name, description, and tips on how to obtain it. These get saved to the database and rendered as the user's checklist.\n\nFor Pro users, a chat endpoint passes the user's question along with their application context (country, purpose, document list) to Gemini and streams back a practical answer. The AI stays focused on visa topics — if someone asks something unrelated, it redirects them back to their application.\n\nWhat I Learned\n\nAurora express config has hidden constraints. The one-click setup is convenient but locks you into IAM authentication. If you need password-based auth, use Standard Create and configure it manually.\n\nIAM auth is actually better once it's working. No static credentials to rotate, no passwords to leak. Short-lived tokens generated per-connection is a genuinely more secure pattern than a DATABASE_URL sitting in an environment variable.\n\nServerless v2 cold starts are real. After a period of inactivity the cluster scales to 0 ACUs and the first request takes a few seconds longer. For a production app you'd want a minimum capacity of 0.5 ACUs to avoid this.\n\nDjango's pluggable database backend system is powerful. I didn't know you could swap out the database backend with a custom class until this project. It's a clean extension point that made the IAM token solution possible without touching any application code.\n\nTry It\n\nLive demo: [https://application-tracker-jet.vercel.app](https://application-tracker-jet.vercel.app)\n\nBackend API: [https://application-tracker-production-3af2.up.railway.app](https://application-tracker-production-3af2.up.railway.app)\n\nI built VisaTrack for the H0 — Hack the Zero Stack with Vercel v0 & AWS Databases hackathon. If you're building something similar or have questions about the Aurora IAM setup, drop a comment below.", "url": "https://wpnews.pro/news/how-i-built-a-visa-tracker-with-django-aurora-postgresql-and-react", "canonical_source": "https://dev.to/elias_benfridja_41f2f87fe/how-i-built-a-visa-tracker-with-django-aurora-postgresql-and-react-3ijn", "published_at": "2026-06-28 22:48:45+00:00", "updated_at": "2026-06-28 22:58:35.995630+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "ai-products"], "entities": ["Django", "Amazon Aurora PostgreSQL", "React", "Vercel", "Railway", "AWS", "Google Gemini", "VisaTrack"], "alternates": {"html": "https://wpnews.pro/news/how-i-built-a-visa-tracker-with-django-aurora-postgresql-and-react", "markdown": "https://wpnews.pro/news/how-i-built-a-visa-tracker-with-django-aurora-postgresql-and-react.md", "text": "https://wpnews.pro/news/how-i-built-a-visa-tracker-with-django-aurora-postgresql-and-react.txt", "jsonld": "https://wpnews.pro/news/how-i-built-a-visa-tracker-with-django-aurora-postgresql-and-react.jsonld"}}