Skip to content
- Introduction
- The choice of languages is more varied, as long as it takes in an HTTP
request and spits out HTML
- Popular: PHP, C#, Ruby, Python and Java
- Back-end handles application logic and data management and works with
applications, databases, and servers
- Back-end interacts with the front end often through APIs
- Back-end developers build APIs that front-end developers can use to
integrate the client with the server-side
- REpresentational State Transfer (REST)

- Architectural style for providing communication standards between devices on
the web
- Refer to individual data objects as resources
- Every resource/resource collection has a unique address associated with it -
its URL
- Stateless and separate the concerns of client and server
- Separation of client and server
- Development of client and server can be independent as long as each side
knows what format of messages to send to the other
- With a REST interface, different clients hit the same REST endpoints,
perform the same actions, and receive the same responses
- Statelessness
- The server does not need to know about the state of the client and vice
versa
- Communication between server and client
- Clients send requests to retrieve or modify resources, servers send response
to those requests
- Making requests
- an HTTP verb, which defines what kind of operation to perform
- GET --- retrieve a specific resource (by id) or a collection of resources
- POST --- create a new resource
- PUT --- update a specific resource (by id)
- DELETE --- remove a specific resource by id
- a header, which allows the client to pass along information about the
request
- The type of content that the client is able to receive from the server →
the Accept field
- Follows
MIME types
- a path to a resource
- In RESTful APIs, paths should be semantic to the client
- Hierarchical and descriptive path such as
fashionboutique.com/customers/223/orders/12
- Accessing a single resource would need an id appended to the path
- Referring to list or collections of resources does not entail adding an id
- an optional message body containing data
- Sending responses
- Content types
- When server sends a data payload to the client, there must be a
content-type in the header of the response
- Match with one of the options in the Accept field of the request
- Response codes - Alert the client to info about the success of the operation

- HTTP request types
- HTTP standard specifies two properties for request types: safety and
idempotency
- HTTP GET and HEAD requests should be safe
- Taking no actions other than retrieval
- Cause no side effects on the server
- Adhering to RESTful principles in our API guarantees safe GET and HEAD
requests
- All HTTP requests except POST should be idempotent
- The side effects of N > 0 identical requests are the same as for a single
request
- Adhering to RESTful principles in our API guarantees idempotent GET, HEAD,
PUT, and DELETE requests
- Same origin policy and CORS
- A URL’s origin is defined as protocol (scheme) + hostname + port
http://example.com:80/index.html
- protocol: http
- host: example.com
- port: 80
- If the referenced resource (from the fetched HTML document) is fetched using
a URL that does not have the same origin as the source HTML, the browser
will have to check the Access-Control-Allow-origin response header
- If it contains * or the URL of the source HTML, the browser will process
the response, otherwise it will refuse to process it and throw an error
- Same-origin policy is a security mechanism implemented by browsers to
prevent session hijacking and other security vulnerabilities
- Legitimate cross-origin requests are enabled with CORS
- Allows restricted resources (images, stylesheets, scripts, iframes, and
videos) to be requested from another domain outside the domain from which
the resource was served
- But by default, JS code that runs in a browser can only communicate with a
server in the same origin
- Backend web architecture
- Components
- The server. This is the computer that receives requests
- Personal computer used as server during development
- The app. This is the application running on the server that listens for
requests, retrieves information from the database, and sends a response
- Contains logic about how to respond to various requests based on the
HTTP verb and the URI
- Route is a pair of an HTTP verb and a URI
- Routing is matching requests to appropriate routes/endpoints, which
triggers handler functions to process and send a response
- Some of these handler functions will be middleware
- Middleware might modify the request object, query the DB, or otherwise
process the incoming request
- Ends by passing control to the next middleware function, rather than
sending a response
- One middleware ends the request-response cycle with a response to the
client
- Each route can have one or many handler functions that are executed when
a request to that route is matched
- The database. Databases are used to organize and persist data.
- An interface to save data in a persistent way to memory
- Reduces load on memory of main server and allows data persistence when
server down
- Requests to server might require DB queries
- Web API
- An interface created by the back-end
- A collection of endpoints and the resources these endpoints expose
- Defined by the routes it defines, and responses client can expect
- One Web API can provide data from different front-ends
- Backend frameworks
- Common features
- Work directly with HTTP requests and responses
- Every “view” function (a request handler) receives an HttpRequest object
and return an HttpResponse object
- HttpRequest contains request information
- HttpResponse contains the formatted output
- Routing requests to appropriate handlers
- Map URL patterns to specific handler functions
- Interacting with DBs
- Object-Relational Mapper (ORM) is an abstraction database layer that
abstracts DB read, write, query, and delete operations
- ORM benefits
- Can change underlying DB implementation without changing the code that
uses it
- Validation of data can be implemented within the framework
- The model is the object used to define the structure of a record
- Specifies field types, which may provide field-level validation
- Field definition help specify their maximum size, default values,
selection list options, help text for documentation, label text for
forms etc.
- Supporting sessions and user authorization
- Formatting output (HTML, JSON, XML)/Rendering data
- Provides templating systems for HTML, JSON, or XML output
- Placeholders in the templates will be replaced with values passed in
from the view function when the page is rendered
- Improving security against web attacks
- Node.js
- An asynchronous event-driven JavaScript runtime designed to build scalable
network applications
- JS runtime means that you can run JS from any machine without going
through a web browser
- Adds some functionality to browser-based JS
- Read and write local files
- Create HTTP connections
- Listens to network requests
- In the browser, you do not have access to Node APIs like filesystem access
functionality
- In Node, you do not have access to the DOM, or Web Platform APIs, or
objects provided by the browser
- Node assumes it’s always running in a dev environment
- By setting NODE_ENV=production environment variable, you can signal Node
that you are running in prod
- Execute the command export NODE_ENV=production in the shell
- Or put it in shell config file (e.g .bash_profile with the Bash shell)
- Can also apply the environment variable by
- NODE_ENV=production node app.js
- TypeScript → TS compiler → JS → Node.js
- Tell the OS which interpreter to use for running JS scripts with a “shebang”
line
- #!/usr/bin/env node
- The script should have executable permissions
- The process core module of Node provides the env property that hosts all
environment variables that were set at the moment the process was started
- USER_ID=239482 USER_KEY=foobar node app.js
- Passes the user USER_ID and USER_KEY
- process.env.USER_ID; // “239482”
- process.env.USER_KEY; // “foobar”
- Accesses the environment variables inside the script
- Configure bash scripts to export variables in prod
- Create an .env file in the root directory of project and use dotenv
package to load them during runtime
- # .env file
- USER_ID=“239482”
- USER_KEY=“foobar”
- NODE_ENV=“development”
- # .js file
- require(‘dotenv’).config();
- process.env.USER_ID; // “239482”
- process.env.USER_KEY; // “foobar”
- process.env.NODE_ENV; // “development”
- Make HTTP requests with the Axios library or the HTTPS core module
- Interact with the file system using the fs core module
- URL browser-compatible class
- Handle events with the events core module
- Recommended project structure ├── index.js → starts the application ├──
app.js → contains actual application, connect to DB ├── build │ └── … ├──
controllers │ └── notes.js → define event handlers of routes in Router
object, to be used as middleware ├── models │ └── note.js → define schema
├── package-lock.json ├── package.json ├── utils │ ├── config.js → handle
environment variables │ ├── logger.js → wrap native log functions to save to
file or send to external logging services │ └── middleware.js → custom
middleware
- Separate test, prod, and dev environments
- Examples
- “start”: “cross-env NODE_ENV=production node index.js”
- “dev”: “cross-env NODE_ENV=development nodemon index.js”
- “test”: “cross-env NODE_ENV=test jest —verbose —runInBand”
- Use cross-env as production dependency to ensure cross-platform
compatibility
- Assess environment with process.env.NODE_ENV
- Test API with Jest and supertest
- Using BaaS for backend
- Firebase services
- Firebase Authentication to easily allow your users to sign into your app.
- Cloud Firestore to save structured data on the cloud and get instant
notification when data changes.
- Cloud Storage for Firebase to save files in the cloud.
- Firebase Hosting to host and serve your assets.
- Firebase Cloud Messaging to send push notifications and display browser
popup notifications.
- Firebase Performance Monitoring to collect user performance data for your
app.
- Integrate Firebase to JS project
- Databases
- Types
- Relational
- Non-relational
- Express
- Provides mechanisms to
- Write handlers for requests with different HTTP verbs at different URL
paths (routes)
- Integrate with “view” rendering engines in order to generate responses
by inserting data into templates
- Set common web application settings like the port to use for connecting,
and the location of templates that are used for rendering the response
- Add additional request processing “middleware” at any point within the
request handling pipeline
- Express passes control from one middleware/route to the next by using next()
- next() would simply move onto the next middleware/route handler
- next(<param>) would continue to the error handler middleware
- Can register middleware to all routes/specific routes/specific operations
- Express error handlers
- Order of middleware loading
- json-parser middleware should be among the very first
- unknownEndpoint should be next to the last middleware, just before the
error handler
- A router object is an isolated instance of middleware and routes
- Think of it as a mini-application capable only of performing middleware
and routing functions
- Every Express app has a built-in app router
- Use express-async-errors to eliminate try-catch blocks while using
async/await
- If an exception occurs in an async route, the execution is automatically
passed to the error handling middleware
- User admin
- In relational DBs, save user’s ID as foreign key for respective object
- Can do all sorts of stuff in document DBs because they don’t support join
queries
- Schema-less DBs like Mongo require radical design decisions about data
organization
- Token authentication

- User starts by logging in using a login form implemented with React
- This causes the React code to send the username and the password to the server
address /api/login as a HTTP POST request
- If the username and the password are correct, the server generates a token
that somehow identifies the logged-in user
- The backend finds the user in the DB with the supplied username and compare
password with stored passwordHash
- The token contains the username and user id in an encrypted form, which can be
decoded in authorized endpoints to obtain the original username and userid
using the same secret string used to sign the token → do not need to include
username and user id in every request, only need to login, get token and
include token with every request
- The token is signed digitally, making it impossible to falsify (with
cryptographic means)
- The backend responds with a status code indicating the operation was
successful and returns the token with the response
- The browser saves the token, for example to the state of a React application
- When the user creates a new note (or does some other operation requiring
identification), the React code sends the token to the server with the request
- The server uses the token to identify the user
- Can use express-jwt for multiple interfaces requiring identification
- Token authentication must always be used over HTTPS
- Problems of token-based authentication
- API has a blind trust to the token holder
- To revoke the access rights of the token holder - Limit the validity period
of a token - Safer the shorter the period is - requires more re-logins -
Save info about each token to backend DB and check for each API request if
the access right corresponding to the token is still valid - Called
server-side session - Increased complexity and performance hit - Common to
save the session corresponding to a token to a key-value DB (Redis) - Token
can just be a random string - Cookie can be used instead of Authorization
header
- Django

- Should use same DB for prod and dev
- MongoDB
- Stores data records as documents, gathered together in collections
- A database stores one or more collections of documents
- Document databases like Mongo are schemaless
- Mongoose
- High-level API to use MongoDB directly in JS code, better than the official
MongoDB Node.js driver library
- An object document mapper (ODM)
- The idea of Mongoose is that data stored in DB is given a schema at the
application level that defines the shape of the documents stored in any
given collection
- Saving JS objects as Mongo documents is straightforward
- Schema
- In Mongoose, everything is derived from a schema
- Each schema maps to a MongoDB collection and defines the shape of the
documents in that collection
- Each key in the schema defines a property which will be cast to its
associated SchemaType
- Permitted SchemaTypes
- String
- Number
- Date
- Buffer
- Boolean
- Mixed
- ObjectId
- Array
- Decimal128
- Map
- UUID
- Schema — (compilation) → Model
- Model
- Fancy constructors compiled from Schema definitions, used to construct
documents
- An instance of a model is called a document
- Models are responsible for creating and reading documents from the
underlying MongoDB database
- Comparison with OOP
- Mongoose schemas in MongoDB can be compared to interfaces in programming
languages
- Schemas define the structure and properties that a document should have
- They specify fields, types, default values, and validation rules
- Schemas act as blueprints or contracts for documents
- Mongoose models are similar to classes based on interfaces
- Models represent collections in MongoDB and provide an interface to
interact with the database
- Models allow operations like create, read, update, and delete on documents
- Documents in Mongoose are instances of models, similar to objects being
instances of classes
- You can create new documents using the model, set properties, and save
them to the database
- Various operations like updating fields, running queries, and executing
aggregation pipelines can be performed on documents
- Mongoose’s similarity to programming language constructs makes it
intuitive for developers familiar with object-oriented concepts
- It provides a structured way to work with MongoDB and documents using
JavaScript
- Provides validation as middleware
- Ensure uniqueness of a field with mongoose-unique-validator
- Joins in relational DBs are transactional, the state of the DB does not
change during the time that the query is made
- Join queries in Mongoose are implemented with multiple queries, which does
not guarantee the consistence of the DB state
- Use the populate method and include needed fields