How I Built a Serverless URL Shortener on AWS
2026-04-10
How I Built a Serverless URL Shortener on AWS
I built a serverless URL shortener that converts a long URL into a small, shareable link. The backend runs on AWS, while the user interface is integrated into my Next.js portfolio.
The project gave me a practical way to work with serverless architecture, API design, database operations, redirects, validation, and frontend integration.
What does the application do?
The application supports two main operations:
- A user submits a long URL and receives a unique short code.
- A visitor opens the short URL and is redirected to the original URL.
For example:
Long URL:
https://example.com/articles/serverless-applications/introduction
Short URL:
https://api.example.com/a1b2c3d4
AWS components used
Amazon API Gateway
API Gateway provides the public HTTP endpoints for the application. It receives requests from the portfolio and forwards them to the appropriate Lambda function.
The API has two important routes:
POST /shorten
GET /{code}
POST /shorten creates a short URL. GET /{code} handles the redirect when
someone opens an existing short link.
AWS Lambda
Lambda contains the application logic. Because Lambda runs only when a request arrives, I do not need to create or maintain a continuously running server.
The shortening logic:
- reads and validates the submitted URL;
- generates a unique short code;
- stores the code and original URL;
- returns the generated code to the client.
The redirect logic:
- reads the code from the request path;
- finds its matching long URL;
- returns an HTTP redirect response;
- returns a not-found response if the code does not exist.
Amazon DynamoDB
DynamoDB stores the relationship between each short code and its original URL. A simplified item looks like this:
{
"code": "dc547be2",
"originalUrl": "https://example.com/a/long/url",
"createdAt": "2026-06-25T10:30:00.000Z"
}
The short code works well as the partition key because the redirect Lambda can look up a link directly without scanning the table.
An optional expiry value can also be stored and used with DynamoDB Time to Live if links should be removed automatically.
Amazon CloudWatch
Lambda writes execution logs to CloudWatch. These logs are useful when an API request fails, a database lookup does not return an item, or a redirect behaves unexpectedly.
API Gateway rate limiting
I configured throttling in API Gateway to limit how many requests the public API accepts within a period of time. Large bursts of unnecessary requests can therefore be rejected before they invoke Lambda.
This helps protect the endpoint and keeps service usage and cost under control.
Lambda concurrency cap
I also configured a concurrency cap for the Lambda function. This limits how many instances of the function can run at the same time.
API Gateway throttling controls incoming traffic, while the Lambda concurrency cap protects the compute layer:
Incoming requests
-> API Gateway rate limit
-> Lambda concurrency cap
-> application logic
Using both is useful for a public portfolio project because its expected traffic is small and unlimited scaling is unnecessary.
Architecture
The URL creation flow is:
User
-> Next.js form
-> Next.js API route
-> API Gateway: POST /shorten
-> Lambda
-> DynamoDB
-> short code returned to the user
The redirect flow is:
Visitor opens /{code}
-> API Gateway
-> Lambda
-> DynamoDB lookup
-> HTTP redirect to the original URL
Creating a short URL
The frontend sends a JSON request to the AWS create endpoint:
POST /shorten
Content-Type: application/json
{
"url": "https://example.com/a/very/long/url"
}
The Lambda function returns the generated code and relative short path:
{
"code": "dc547be2",
"shortUrl": "/dc547be2"
}
Returning the code separately is useful for storage and debugging. Returning the relative path keeps the Lambda response independent of a particular custom domain.
Generating the short code
The code should be:
- short enough to share easily;
- difficult to guess accidentally;
- unique within the DynamoDB table;
- safe to place inside a URL path.
A simple implementation can generate a random identifier and check that it does not already exist before saving it. For a larger system, the code length and collision strategy should be selected based on expected traffic.
Handling redirects
When a visitor opens a short link, API Gateway passes the path code to the redirect Lambda. The function retrieves the matching item and returns a redirect response:
{
"statusCode": 302,
"headers": {
"Location": "https://example.com/a/very/long/url"
},
"body": ""
}
The browser reads the Location header and navigates to the original URL.
If no DynamoDB item matches the code, the API returns 404 Not Found instead
of redirecting.
Integrating AWS with my Next.js portfolio
The browser does not call the AWS endpoint directly. The URL-shortener form calls an internal Next.js route:
POST /api/shorten
That server-side route validates the URL and then sends it to API Gateway. The AWS configuration stays in environment variables:
AWS_SHORTENER_API_URL=https://api.example.com/shorten
AWS_SHORTENER_PUBLIC_URL=https://api.example.com
The API key variable is optional because this project does not require an API key.
Converting the relative response into a complete URL
My AWS endpoint returns:
{
"shortUrl": "/dc547be2"
}
If the frontend uses that value directly, the browser interprets it relative to the portfolio domain. It might incorrectly open:
http://localhost:3000/dc547be2
The Next.js API route solves this by combining the returned path with the public AWS URL:
const shortUrl = new URL(
response.shortUrl,
process.env.AWS_SHORTENER_PUBLIC_URL,
).toString();
The user then receives the correct link:
https://api.example.com/dc547be2
Validation and error handling
The portfolio and AWS backend should both validate requests. The current integration checks that:
- a URL was provided;
- it can be parsed as a valid URL;
- it uses the HTTP or HTTPS protocol;
- the AWS request completed successfully;
- the response includes a short URL or code.
The interface also displays loading, success, and error states. After a link is created, the user can open it or copy it to the clipboard.
At the infrastructure level, API Gateway rate limiting reduces excessive incoming traffic, and the Lambda concurrency cap prevents too many function instances from running simultaneously.
Why serverless was a good fit
This project does not need a server running continuously. API Gateway, Lambda, and DynamoDB provide a small set of managed services that scale with incoming requests.
The main benefits are:
- no server maintenance;
- automatic scaling;
- usage-based pricing;
- simple integration between AWS services;
- independent frontend and backend deployment.
Improvements I can add next
The project can be extended with:
- a custom short domain;
- optional custom aliases;
- link expiration using DynamoDB TTL;
- click analytics;
- protection against malicious destination URLs;
- duplicate detection for previously shortened links;
- automated deployment using AWS SAM or the AWS CDK.
What I learned
The most interesting part was not only generating a random code. The complete solution required the create route, redirect route, persistent storage, traffic controls, validation, error handling, and frontend response normalization to work together.
This project helped me understand how small serverless components can be combined into a useful production-style application.