Let‘s Build a Serverless REST API with Angular, Persistence, and Security
Adopting a serverless architecture brings considerable advantages compared to traditional server infrastructure when building web and mobile applications. By eliminating the need to manage servers yourself, serverless enables greater productivity, cost efficiency, and scalability.
In this comprehensive guide, we will demonstrate the benefits firsthand by building a full-stack task management application with Angular, a secure REST API, and a robust persistence layer – all leveraging a serverless backend.
Why Serverless is the Future
Before diving into building our task app, it‘s helpful to understand the compelling benefits driving adoption of serverless platforms over traditional servers:
No Resource Management
With traditional servers, developers spend substantial time managing infrastructure for capacity planning, configuring security policies, monitoring resource usage, applying patches and updates – the list goes on. With a serverless platform, all resource management is fully handled for you. The provider automatically scales compute power and optimizes performance based on demand. This frees developers to dedicate more time to writing application code rather than server ops.
Our task app is a perfect example. Why waste time worrying about infrastructure when you can focus on the functionality that matters most to users?
Pay-Per-Use Cost Model
On traditional servers, you pay for reserved compute capacity even when your app is idle. With serverless, you only pay for the exact resources used to execute your code down to the millisecond. This "pay-as-you-go" model unlocks huge cost savings given applications rarely maximize resource utilization.
Cloud platforms like AWS even provide 1 million free requests per month – making serverless ideal for low traffic apps and proof-of-concepts. For an app like ours, serverless is extremely cost-effective.
Serverless platforms offer significant cost reductions compared to traditional servers
Faster Delivery of Features
When developers avoid wasting time on infrastructure ops, they can build and deliver application features much faster. For lean teams especially, choosing serverless means pushing innovations to market quicker and satisfying customers faster by accelerating development velocity.
For our task app, serverless will help us bootstrap the first functional version incredibly rapidly. We can build core features around task management first then expand over time – all while avoiding dev ops distractions.
Simplified Scalability
One of the most cited benefits of serverless is nearly infinite, automated scalability. Serverless platforms easily handle traffic spikes without capacity planning. Traditional servers require manual intervention to scale-up. This simplifies workflows and makes applications highly elastic without administrative burden.
For event-driven apps with variable traffic, like our task manager, serverless platforms easily soak large workloads when demand peaks while keeping costs minimal when traffic is low.
Serverless platforms smoothly handle workload spikes and valleys
Enhanced Security
Maintaining rigorous security protections is challenging with DIY servers. Keeping systems hardened against vulnerabilities while applying frequent patches is tedious manual work. With serverless platforms, security responsibilities transfer to the provider. Leading vendors implement rigorous controls around data encryption, infrastructure hardening, penetration testing, DDoS mitigation, and compliance monitoring which greatly reduces risk.
For any app handling user data, like our task manager, leveraging serverless means leveraging enterprise-grade security measures by default. This gives developers and users much needed peace-of-mind.
The benefits clearly demonstrate why serverless adoption is accelerating across application development. By eliminating overhead, it allows builders to deliver better products faster. Now let‘s see this firsthand by building our task management app!
Scaffolding the Angular Application
We will use Angular CLI to quickly scaffold a basic Angular application with configured testing, linting, and other integrated tools:
# Install Angular CLI globally
npm install -g @angular/cli
# Create new app
ng new task-app
cd task-app
# Serve the app
ng serve
Angular CLI has many time-saving benefits:
- Generates app skeleton with routing, CLI builder, and test harness
- Central point for generating components, services, modules, etc
- Integrated bundling for development and production
- Simplified build configuration
- Easy integration with CI/CD pipelines
This streamlines our development workflow from the start allowing faster iteration as we build out the application.
With the foundation in place, let‘s configure user authentication next before adding any additional features.
Adding Authentication with Auth0
Implementing a secure, scalable user authentication layer from scratch is challenging. By leveraging Auth0, we can integrate enterprise-grade identity management in minutes without managing servers ourselves.
First, sign up for a free Auth0 account. We will configure Single Page Application (SPA) settings:
// Configure Auth0 credentials
AUTH_CONFIG = {
domain: ‘<AUTH0_DOMAIN>‘,
clientId: ‘<AUTH0_CLIENT_ID>‘,
redirectUri: ‘http://localhost:4200‘,
responseType: ‘token‘,
scope: ‘openid profile email‘
};
- Domain and clientId authorize our app
- redirectUri handles the login callback
- responseType, scope request an access token with user info
Next install the libraries:
npm install auth0-js jsonwebtoken
auth0.js simplifies login/logout while jsonwebtoken parses JWT data.
Then load credentials and handle authentication events:
// Retrieve Auth0 credentials
const AUTH_CONFIG = {...};
// Parse hash fragment for JWT
const parseHash = (hash = ‘‘) => {
const encodedToken = getParameterByName(hash, ‘access_token‘);
const token = decodeJwt(encodedToken);
return token;
}
// Check token expiry
const checkExpiry = () => {
const token = localStorage.getItem(‘token‘);
if(!token || decodeJwt(token).exp < Date.now()/1000){
return false;
}
return true;
}
// Log user in
const login = () => {
webAuth.authorize();
}
// Log user out
const logout = () => {
localStorage.removeItem(‘token‘);
}
With credentials loaded and auth helpers in place, we can handle login/logout events in our components.
Auth0 simplifies what would normally be complicated authentication logic. Externalizing user management eliminates considerable dev ops complexity.
Now with identity services handled, we‘re ready for the data persistence layer.
Persisting Data with MongoDB Atlas
For storing app data, we will use MongoDB Atlas which provides a fully managed MongoDB-as-a-Service used by over 2 million developers. Atlas handles time-consuming admin tasks like server provisioning, upgrades, uptime monitoring, and backup management.
After creating a free cluster, we need to whitelist connection IP addresses. Currently, just whitelist your local IP. Later we will add our serverless API:
# Retrieve local IP address
$ curl icanhazip.com
# Whitelist address
# https://cloud.mongodb.com/v2/621c***/access/add
We interact with Atlas through a connection URI:
mongodb+srv://<username>:<password>@cluster0.zadqi.mongodb.net/myFirstDatabase
This handles authentication and points to our cluster. With MongoDB hosted, we avoid managing our own instances while leveraging a fully managed, highly performant database-as-a-service.
Now we can persist data. Onwards to the final piece: the serverless REST API.
Creating the Serverless REST API
We will leverage a serverless architecture for our backend API to offload infrastructure management. Express provides a simple framework for building REST endpoints. We will deploy the API as a Webtask which automatically scales while only charging for execution time.
First, scaffold the API with Express:
const express = require(‘express‘);
const jwt = require(‘express-jwt‘);
const mongoose = require(‘mongoose‘);
const app = express();
app.use(express.json());
// Connect to MongoDB
mongoose.connect(process.env.MONGODB_URI);
// Validate JWT tokens
app.use(jwt({ secret: process.env.AUTH0_SECRET }));
// API routes
app.get(‘/tasks‘, getTasks);
app.post(‘/tasks‘, createTask);
module.exports = app;
Next we connect to MongoDB using our Atlas cluster URI secured in an environment variable.
To validate requests, we leverage express-jwt which checks for valid JWTs on each call. This ensures only authenticated users access the API.
With the foundation ready, we define CRUD routes for task entities.
To deploy as a Webtask:
$ npm install -g wt-cli
$ wt init # Login to Webtask CLI
$ wt create app.js
--name task-api
--secret AUTH0_SECRET=${AUTH0_SECRET}
--secret MONGODB_URI=${MONGODB_URI}
Just like that our REST API goes live! Webtask handles provisioning, scaled execution, security patching and more without us managing servers.
Now we are ready to connect our Angular frontend.
Connecting the Angular Frontend
With authentication and data persistence handled, we can focus on bringing our Angular application to life.
Let‘s build out the main components:
TaskService – Handles API integration
TaskListComponent – Displays tasks
TaskFormComponent – Adds new tasks
The service encapsulates interacting with our API:
@Injectable()
export class TaskService {
api = ‘https://webtask.it.auth0.com/api/run/wt-************/‘;
constructor(private authHttp: AuthHttp) {}
getTasks() {
return this.authHttp.get(this.api + ‘/tasks‘);
}
}
authHttp automatically handles sending authentication credentials from Angular JWT.
The component subscription logic would look like:
@Component(...)
export class TaskListComponent {
tasks = [];
constructor(private taskService: TaskService) {}
ngOnInit() {
this.taskService.getTasks()
.subscribe(tasks => this.tasks = tasks);
}
}
While barebones, this connects the full-stack architecture! Frontend components can consume backend APIs transparently.
Fleshing out the UI using Angular Material components and adding routing completes the core application.
Client-Side Architecture Advantages
Building Angular as a client-side SPA over a traditional multi-page application brings significant advantages:
Faster UX: No page reloads required, all logic happens via components
Decoupled Code: Frontend consumes backend APIs rather than intertwined server-rendered code
SPA Efficiency: Application loaded once upfront minimizing network requests
SEO Friendly: Angular Universal and prerendering optimize pages for search engines
Progressive Enhancement: Features can layer over core content for flexible expansion
SPA frameworks like Angular combined with serverless backends unlock extremely productive development of web applications. Eliminating infrastructure woes allows builders to deliver more features faster.
Deployment Using Amplify and AWS
To host our Angular code as static assets for global delivery, we can leverage Amazon CloudFront, S3 and Amplify Console for simplified hosting:
Amazon S3 – Scalable cloud object storage
Amazon CloudFront – Content delivery network
AWS Amplify – Angular deployment automation
Configure Amplify pipelines:
$ npm install -g @aws-amplify/cli
$ amplify configure
$ amplify init
$ amplify add hosting
$ amplify publish
In minutes our app goes live on globally distributed infrastructure leveraging AWS security monitoring, automatic scaling capabilities and content acceleration.
We could also deploy our bundled assets to any host like Netlify, Azure Storage, or GitHub Pages. This flexibility and simplicity illustrates why static site deployment continues rapid adoption over traditional, monolithic architecture.
Prioritizing Time-to-Value with Serverless
By leveraging a serverless architecture containing managed services like Auth0, MongoDB Atlas, and AWS backend, we built a custom full-stack application rapidly without needing to operate any servers or infrastructure ourselves!
The benefits of this serverless approach include:
No Ops Overhead: No wasting time on resource management, scaling, or monitoring
Improved Security: Leverage enterprise-grade security protections
Faster Delivery: Accelerate build/release cycles focusing on app code
Increased Scalability: Absorb spikes in traffic automatically
Cost Savings: Significant reductions in total spending
For many applications, serverless is a no brainer helping developers "ship more and operate less" allowing more time innovating on end-user experiences.
While our core task management foundation is solid, limitless potential features could build upon it like rich text notes, reminders, categories, file attachments, analytics, and more. The key is establishing a flexible platform.
Let‘s explore just a few ways we could expand this application over time.
Mapping an Enhancement Roadmap
With a solid full-stack architecture built quickly thanks to our serverless approach, we have an adaptable foundation allowing incremental enhancement:
Task Analytics and Reporting
- Build visualizations on task volume, completion rates, duration metrics
- Integrate BI tools like Tableau, Looker, Sisense to derive insights
Remote Teams and Collaboration
- Add user management with invites and permission groups
- Commenting APIs so tasks can be discussed
- Real-time notifications when tasks are added/completed
Mobile Support and Offline Access
- React Native or Ionic mobile frontends
- Local caching for offline productivity
- Push notification alerts and reminders
Intelligent Recommendations
- Custom algorithms suggesting reminders and due dates
- AI classifiers categorizing tasks automatically
- Smart assignment based on user work patterns
External Integrations
- Import tasks from emails, chat apps, calendars
- Zapier and IFTTT workflows automating data flows
- Slack bots interacting conversationally
Nearly anything we dream up could integrate cleanly thanks to the structured full-stack foundation following API-first principles.
Conclusion
In this guide, we built an entire custom application leveraging leading technologies – Angular, MongoDB, Auth0 and more – all running on serverless infrastructure.
The benefits compared to traditional servers allow smaller teams to punch above their weight class by eliminating dev ops toil enabling faster delivery of customer-impacting capabilities.
While we explored just one potential serverless architecture pattern, many other effective combinations exist across cloud providers like AWS, GCP and Azure who continue expanding their serverless offerings.
Additional innovations like Docker containers and orchestrators like Kubernetes are also driving the broader trend towards "NoOps" application development.
By learning these emerging approaches early combined with industry-leading frontend frameworks like Angular, developers position themselves competitively for the future while enabling their organizations to better meet customer needs.
What features might you build next upon this serverless setup? The possibilities are endless.
I welcome your thoughts via email or Twitter!