Week 1 | Lesson 1

Introduction to Backend Development

in Kotlin

Why Kotlin?

Why Kotlin?

Java has been the dominant language for backend development for many years.
Kotlin is considered a modern alternative to Java.

Kotlin is fully interoperable with Java, which means that you develop and deploy Kotlin applications in the same way as Java applications, and you can use existing Java libraries and frameworks with Kotlin.

Both Java and Kotlin are a solid choice for backend development because of their design:

  • Statically typed languages, which means developers can catch many errors at compile time.
  • Run on the Java Virtual Machine (JVM), which means that they can run on any platform that supports it.
  • Can be containerized easily and is easy to deploy and scale in cloud environments.
  • Have a large ecosystem of libraries and frameworks that can be used to build applications.
  • Have a strong community and support from major companies (e.g., Google for Android, JetBrains for Kotlin).
  • There is some performance overhead with JVM, but it is generally negligible for most applications and JVM can be tuned for performance.

What we will learn in this course is not specific to Kotlin and can be applied to any backend language.


Also, an honest answer is that it is the language I know best, and therefore I can teach it best.

Development Environment

IDE

What is Integrated Development Environment (IDE)

Being able to efficiently use an IDE is just as important as being able to write code.
Gives you a set of tools that you need as a developer.
  • Provides code editor with syntax highlighting
  • Easy ways to manage code, project and builds
  • Helps your productivity
    contextual suggestions, autocomplete, code navigation, refactoring, language tip
  • Helps you avoid some errors in your programs
    can warn you about problematic code
    gives you tools inspect your code
    gives you tools test your code
  • Integrates tools
    source code management, such as git
    database clients
    documentation
    project management tools
    AI
  • Usually has a community led plugin ecosystem

Your first Kotlin program

Exercises, Submission & Grading

Prerequisites

You will need:

  1. A computer with a modern operating system (Windows, macOS, Linux).

  2. A text editor or IDE for writing Kotlin code.
    We will use IntelliJ IDEA Community Edition, which is free and widely used.
    You can download it from https://www.jetbrains.com/idea/download/.

  3. Git for version control.
    You can download it from https://git-scm.com/downloads.

  4. A GitHub account for submitting your code and collaborating with others. You can create an account at https://github.com

Your first Kotlin program

You will use GitHub Classroom for all assignments in this course.

Assignment

  1. Accept the assignment
    Click on the assignment link provided in the course materials. This will create a private repository for your work.

  2. Clone the repository
    git clone [your-repository-url]

  3. Work on your solution
    Complete the assignment in your local environment.
    See README.md in the repository for instructions on what to implement.

Solution Submission and Grading

Once your code is running, you need to submit it for grading.

Submission

  1. Commit and push your changes
    git add .
    git commit -m "Complete assignment"
    git push

  2. Verify submission
    Check your GitHub repository to ensure all changes have been pushed.


Grading

  • Assignments will be automatically graded using tests that run when you push your code.
  • You can see the test results in the "Actions" tab of your GitHub repository.
  • Some assignments may also include manual code review by instructors.
  • Feedback will be provided as comments in your repository or through the classroom platform.

Backend Development

What is "Backend"?

Backend commonly refers to the server-side of an application, which is a process that runs on a server and handles core logic, data management, user authentication, business rules, and integrations with other systems.
It handles things that can’t, or shouldn’t, happen in the user’s browser or app directly.

A typical backend of an application consists of several components that work together to provide the functionality.

  • Server
    The machine or cloud service that runs the backend code.
  • Application Logic
    The code that implements the business rules and processes.
  • Database
    Where data is stored persistently (e.g., user accounts, application state).
  • APIs
    Interfaces for clients (web, mobile, etc.) to interact with the backend.
  • Security
    Mechanisms for authentication and authorization and data protection.

Why Applications Need a Backend?

Most applications that require user accounts, data storage or real-time interactions will have a backend.

What is handled by the backend?

  1. For multi-platform applications, the backend provides a common foundation that all clients (web, mobile, desktop) can rely on for consistent behavior and data access.
  2. For multi-user applications, the backend allows user interactions, roles, data sharing, and real-time updates.
  3. Having a backend allows applications to scale, manage resources and maintain security across different devices and users.

Some applications may not need a backend:

  • Simple static websites
  • Standalone tools, calculators or utilities
  • Local-only games

But even these can evolve to require one — for analytics, syncing, personalization, or collaboration.

What Kinds of Applications Typically Have a Backend?

And what do they use it for?
Application Type Example Backend Role
Web Apps E-commerce site, dashboard Data APIs, authentication, payment handling
Mobile Apps Messaging, social, travel apps Sync data, store media, push notifications
Desktop Apps Collaboration tools, IDEs Real-time sync, cloud storage, user accounts
IoT / Smart Devices Smart lights, wearables Device management, remote control, firmware updates
Games Online multiplayer games Matchmaking, scoring, anti-cheat, player data
APIs / Developer Tools Stripe, Firebase, OpenAI Pure backend — no UI, only serves data or actions to other apps

Responsibilities of Backend

Responsibilities of Backend

What does the backend do?
  • Business Logic
    Enforcing rules and workflows (e.g., checking if a user can book a ticket).

  • Data Persistence
    Storing and retrieving user or application data (e.g., accounts, messages, files, transactions).

  • Multi-user Coordination
    Managing interactions between different users and devices.

  • Security
    Safely managing sensitive operations (e.g., password handling, access control).

  • Interfacing with Other Services
    Talking to external APIs (e.g., payment gateways, recommendation engines).

  • Performance and Resource Management
    Offloading heavy computation or long-running processes.

Business Logic

Business Logic is a set of rules, calculations and workflows that determine how data is processed to fulfill the business requirements.

Business Logic refers to the fact that this code is specific to the business domain (e.g., e-commerce, healthcare, finance, entertainment, ...).

It is the part of the application that defines how the application behaves and operates to fulfill the business requirements (to address customer needs and problems).

It may include rules for processing data, calculations, workflows based on user actions, and interactions with other systems or services.

Data Persistence

Data persistence is the ability to store, retrieve and update application data.

Typically, this is done using a database which itself is an external resource that the backend interacts with.

The backend is responsible for managing the connection to the database, executing queries, and ensuring data integrity in accordance the business rules.

Multi-user Coordination

Multi-user coordination is the ability to manage interactions between different users and devices.

This is especially important in applications that allow multiple users to interact with each other, such as social networks, messaging apps, or collaborative tools.

The backend is responsible for managing user sessions, handling concurrent requests, and ensuring that users can interact with each other in a consistent and reliable way.

Security

Security involves protecting sensitive data and operations.
Security is a critical aspect of backend development.

The backend is responsible for implementing security measures such as user authentication, authorization, data encryption, and protection against common vulnerabilities (e.g., SQL injection, cross-site scripting).

User authentication is the process of verifying the identity of a user.

User authorization is the process of determining what actions a user is allowed to perform.

Interfacing with Other Services

Interfacing with other services allows the backend to extend its functionality by third party integrations.

Quite often, the backend needs to interact with external services or APIs to provide additional functionality, such as payment processing, email notifications, or data enrichment.

The backend is responsible for managing these integrations, handling API requests and responses, and ensuring that the data exchanged with external services is consistent and secure.

Performance and Resource Management

Backend applications often need to handle large volumes of data, process complex calculations, or perform long-running tasks.

The backend is responsible for optimizing performance, managing resources efficiently, and ensuring that the application can scale to handle increased the load without compromising user experience.

This may involve techniques such as caching, load balancing, asynchronous processing, and using distributed systems.

A well-designed backend should be able to be scaled horizontally (adding more servers) or vertically (upgrading existing servers)

Also, the backend should be designed to be resilient and fault-tolerant, so that it can recover from failures quickly and without losing data or disrupting user experience.

Backend should also provide metrics and logging to monitor performance, detect issues, and analyze usage patterns.

Application Architecture

Common Architecture Patterns

There are several common architecture patterns that are used in the development of software applications.

These are high-level application architecture patterns used to define the structure of the application and the way in which the different components of the application interact with each other.

Some of the most common architecture patterns include:

  • Monolithic Architecture
  • Microservice Architecture
  • API Gateway Architecture
  • Serverless Architecture
  • Event-Driven Architecture

Monolithic Architecture

Monolithic architecture is a software architecture pattern where all the components of the application run as a single unit.

Monolithic architecture tends to be tightly coupled, which can make it difficult to scale and maintain the application over time.

  • When to use
    • Small projects or MVPs.
    • Early-stage startups.
    • Teams with limited resources.
  • Pros
    • Easier debugging with one codebase.
    • Simpler to develop and deploy. ** In terms of needing simper infrastructure.
  • Cons
    • Difficult to scale certain parts independently.
    • Harder to manage as the codebase grows.
    • Limited error resilience.
    • Difficult to develop and deploy. ** Monoliths can have many dependencies to for developers, that may mean a lot of setup.

Monolithic Architecture Diagram

Monolithic Architecture

Microservice Architecture

An architecture that decomposes the system into smaller, (relatively) independent services.
  • When to use
    • Large, complex systems.
    • Teams that are distributed or domain-focused.
    • Scalability is a top priority.
  • Pros
    • Independent scaling and deployment.
    • Fault isolation (failures in one service don't affect others).
    • Easier to adopt different tech stacks per service.
  • Cons
    • Complex to manage (e.g., inter-service communication).
    • Potential for high latency between services.
    • Requires solid observability (monitoring, logging).
  • Pitfalls
    • Be aware of distributed monoliths!

Microservice Architecture Diagram

Microservice Architecture

API Gateway Architecture

Centralizes all API traffic, often for microservices and serverless backends.
  • When to use
    • Systems with multiple backend services.
    • Teams needing centralized authentication, logging, or throttling.
  • Pros
    • Centralized management for APIs.
    • Reduced cross-cutting concerns (e.g., rate limiting, CORS).
  • Cons
    • Can become a single point of failure.
    • Latency and complexity if overloaded.

API Gateway Architecture Diagram

API Gateway Architecture

Serverless Architecture

Uses cloud-managed services where you write and deploy functions instead of managing infrastructure.
  • When to use
    • Event-driven systems (e.g., IoT data, notifications).
    • Applications with unpredictable or spiky traffic.
  • Pros
    • Automatic scaling.
    • Reduced operational complexity.
    • Pay-per-use model.
  • Cons
    • Cold-start latency.
    • Vendor lock-in risks.
    • Debugging and monitoring can be more complex.

Event-Driven Architecture

Systems that react to and propagate events across services (e.g., Kafka, RabbitMQ).
  • When to use
    • Systems with high-frequency event generation.
    • IoT and real-time analytics.
    • Applications with loosely coupled services.
  • Pros
    • Real-time processing and responsiveness.
    • Highly scalable and decoupled.
  • Cons
    • Requires careful event design to avoid excessive coupling.
    • Complex debugging and replaying of events.

How to decide?

You will get it wrong!

And you will re-do it.

And you will still get it wrong again.

And then you will re-do it again.

And it will never be perfect.

And that's OK.


Embrace failure, learn from it, and go on.

12-Factor Applications

12-Factor Applications

The 12-Factor App is a methodology for building modern web applications that are scalable, maintainable, and portable.

It was introduced by Heroku in 2011 and has become a widely accepted best practice for building cloud-native applications. Although it's been around for a while, it remains relevant (with some updates). Most of the principles have become industry standards.

The 12 factors are:

  1. Codebase
  2. Dependencies
  3. Config
  4. Backing Services
  5. Build, Release, Run
  6. Processes
  1. Port Binding
  2. Concurrency
  3. Disposability
  4. Dev/Prod Parity
  5. Logs
  6. Admin Processes
We will go through each of these briefly and then discuss how they apply to Kotlin applications as we build our backend.
You don't need to memorize them all right now, just be aware of them.

1. Codebase

One codebase tracked in revision control, many deploys.

This means that there should be a single codebase for the application, which is stored in a version control system (e.g., Git). The same codebase can be deployed to multiple environments (e.g., development, staging, production).

This allows for easier collaboration, code review, and deployment processes.

2. Dependencies

Explicitly declare and isolate dependencies.

This means that all dependencies of the application should be explicitly declared in a dependency management file (e.g., build.gradle.kts for Kotlin). The application should not rely on any implicit dependencies that are not declared.

This allows for easier management of dependencies and ensures that the application can be built and run consistently across different environments.

3. Config

Store configuration in the environment.

This means that all configuration settings for the application should be stored in environment variables or configuration files that are not part of the codebase. This allows for easier management of configuration settings and ensures that sensitive information (e.g., API keys, database credentials) is not stored in the codebase.

This also allows for different configurations to be used in different environments (e.g., development, staging, production).

Secret management tools (e.g., HashiCorp Vault, AWS Secrets Manager) can be used to manage sensitive configuration settings securely.

4. Backing Services

Treat backing services as attached resources.

This means that all external services that the application relies on (e.g., databases, message queues, caching systems) should be treated as attached resources that can be easily swapped out or replaced.

This allows for easier management of external services and ensures that the application can be deployed to different environments without being tightly coupled to specific services.

5. Build, Release, Run

Strictly separate build and run stages.

This means that the build process (compiling code, packaging dependencies) should be separate from the release process (deploying the application). The build process should produce a deployable artifact (e.g., a JAR file) that can be deployed to different environments.

This allows for easier management of the deployment process and ensures that the same artifact can be deployed to different environments.

6. Processes

Execute the app as one or more stateless processes.

This means that the application should be designed to run as one or more stateless processes that can be easily scaled horizontally. The application should not rely on any local state not stored in a backing service (e.g., database, cache).

This allows for easier scaling and ensures that the application can handle increased the load without losing state.

7. Port Binding

Export services via port binding.

This means that the application should be designed to run as a self-contained service that listens on a specific port. The application should not rely on any external web server or container to run.

This allows for easier deployment and ensures that the application can be run in different environments without relying on external infrastructure.

8. Concurrency

Scale out via the process model.

This means that the application should be designed to handle concurrent requests and scale out by running multiple instances of the application. The application should not rely on any shared state between instances.

This allows for easier scaling and ensures that the application can handle increased the load without losing performance.

9. Disposability

Enable fast startup and graceful shutdown.

This means that the application should be designed to start up quickly and shut down gracefully. The application should not rely on any long-running processes or background tasks that can block the shutdown process.

This allows for easier deployment and ensures that the application can be restarted quickly in case of failures.

10. Dev/Prod Parity

Maintain development, staging, and production parity.

This means that the development, staging, and production environments should be as similar as possible. The application should not rely on any environment-specific configurations or dependencies.

This allows for easier testing and ensures that the application behaves consistently across different environments.

11. Logs

Treat logs as event streams.

This means that the application should be designed to produce logs that can be easily consumed and processed by external systems. The application should not rely on any local log files or logging infrastructure.

This allows for easier monitoring and ensures that the application can be debugged and analyzed in real-time.

In modern systems, this rule can be updated to observability, which includes not only logs but also metrics and traces.

12. Admin Processes

Run admin/management tasks as one-off processes.

This means that the application should be designed to run administrative or management tasks as one-off processes that can be executed independently of the main application. The application should not rely on any long-running administrative processes or background tasks.

This allows for easier management and ensures that administrative tasks can be executed without affecting the main application.

Introduction to Java

Brief history of Java

Why do we need to talk about Java first?

While Java and Kotlin are two separate languages, they are closely related. They both run on the Java Virtual Machine (JVM), and they are interoperable. In fact, Kotlin compiles to Java bytecode, which means that it can run on any platform that supports Java. Understanding some basic principles in Java will help you understand Kotlin better.


Java Logo Kotlin Logo

Brief history of Java

  • Developed by Sun Microsystems
  • Introduced in 1995
  • First version available in 1996
  • Open source since 2007
  • Sun Microsystems was acquired by Oracle in 2010
Java Logo Kotlin Logo

Key features of Java

Simple
easy to learn and use, familiar syntax (based on C++), memory management

Object-Oriented
everything in Java is an object

Platform Independent, Portable, Architecture-Neutral
write once, run anywhere (on java virtual machine), compiled to Java byte code, no specific architecture dependent features (for example data types)

Multi-Threaded
enables concurrent task execution

Secure
no pointers, runs inside virtual machine, guards against illegal access to resources

Robust
no pointers, memory management, strong type checking

High Performance
slower than compiled languages, but fast for interpreted language due java byte code being close to native code

Java has two main components ...

Java Runtime Environment (JRE)

The JRE provides the libraries, the Java Virtual Machine (JVM), and other components needed to run applications written in Java. It does not include developer tools such as compilers and debuggers.

As a user, you would use the JRE to run Java programs on your system.

Java Development Kit (JDK)

The JDK includes the JRE as well as a set of development tools for writing and running Java programs. These tools include the Java compiler (javac), an archiver (jar), a documentation generator (javadoc), and other tools needed in Java development.

Since open-sourcing, multiple implementations of JDK have existed, including Oracle JDK, OpenJDK, Amazon Corretto, and others.

As a programmer, you would use the JDK to develop Java applications and JRE to run them.

Introduction to Kotlin

What is Kotlin?

  • Developed by JetBrains and officially released in 2016.
  • Statically-typed programming language that runs on the Java Virtual Machine (JVM).
  • Fully interoperable with Java, which means that you can use Java libraries in Kotlin and vice versa.
  • Designed to improve on Java's shortcomings, and it is considered a modern alternative to Java.
  • It has modern and intuitive syntax, and it is designed to be concise and expressive.
JetBrains Logo

Important features

  • Null safety by distinguishing nullable and non-nullable types
  • Interoperability with Java, allowing developers to use Java libraries in Kotlin and vice versa
  • Conciseness reducing boilerplate code and improving readability
  • Coroutines provide built-in support for coroutines for easy and efficient concurrent programming
  • Extension Functions allowing you to add new functions to existing classes without modifying their source code
  • Data Classes providing a concise way to create classes that only hold data
  • Higher-Order Functions and Lambdas supporting functional programming paradigms
  • Companion Objects providing a way to create static methods and properties in Kotlin
  • Smart Casts used to automatically casts types when certain conditions are met
  • Sealed Classes providing a way to restrict inheritance

Kotlin Releases: Major Versions

  • 2010: Project Kotlin was born. JetBrains unveiled Project Kotlin, a new language for the JVM, which had been under development for a year.
  • 2012: JetBrains open sourced Project Kotlin. The company has set up a Web demo for the language, and a plugin is already available for IntelliJ IDEA 11.
  • 2016: Kotlin 1.0 was officially released. It was considered stable and ready for production.
  • 2017: Google officially announced Kotlin as a first-class language for Android applications development during Google I/O. This played a crucial role in Kotlin's popularity among Android developers.
  • 2019: Google announced Kotlin as its preferred language for Android app developers, meaning that development tooling would be optimized for Kotlin, and that Kotlin-specific APIs would be prioritized.
  • 2020: Kotlin 1.4 released with focusing on improving the performance and tooling.
  • 2021: Release of Kotlin 1.5.0 with stable language features like JVM records, sealed interfaces and the new default JVM IR compiler.
  • 2022: Kotlin 1.6 was released in November 2021.
  • 2023: Kotlin 1.7 was released in June 2023, including the alpha version of the new Kotlin K2 compiler.
  • 2023: Kotlin 1.8 was released in December 2023, 1.8.0 was released on January 11, 2024.
  • 2024: Kotlin 1.9 was released in July 2024, 1.9.0 was released on July 6, 2024.
  • 2024: Kotlin 2.0 was released in May 2024, 2.0.0 was released on May 21, 2024.

Frameworks

Framework

When we talk about frameworks, we usually mean a collection of libraries and tools that help developers build applications in a faster and more productive way.

For example, a framework can provide a set of libraries for ...

  • data access (databases)
  • security (user authorization and authentication)
  • network communication
  • configuration management
  • cloud integration
  • monitoring and logging
  • testing

... and other common tasks, so that developers don't have to write them from scratch.

Frameworks can also provide a set of conventions and best practices for building applications, which can help developers to write code that is more maintainable and scalable.

Popular Frameworks

There are some Kotlin-specific frameworks, but often times, Kotlin developers use Java frameworks, as Java and Kotlin are interoperable and can share ecosystem.

Java

  • Spring Framework
  • Jakarta EE (formerly Java EE)
  • Hibernate
  • Play Framework
  • Apache Struts
  • Quarkus
  • MicroProfile

Kotlin specific

  • Ktor

We will use Ktor in this course, which is a modern, lightweight, idiomatic Kotlin-specific framework for building web applications and microservices.

No Framework vs Framework

Should You Use a Framework?

Build everything from scratch or use battle-tested tools?

No framework

  • + Full control over every part of the system
  • + Good for learning how things work under the hood
  • + Lightweight, no hidden magic
  • - You have to build everything yourself (routing, HTTP handling, etc.)
  • - Reinventing the wheel is time-consuming and error-prone
  • - Hard to scale and maintain in real-world projects


With framework (like Ktor)

  • + Ready-to-use features (routing, middleware, JSON handling, authentication, etc.)
  • + Speeds up development, especially for teams
  • + Community support and documentation
  • + Focus on business logic instead of boilerplate code
  • + Encourages best practices and convention-over-configuration
  • - Adds abstraction layers — might feel “magical”
  • - Learning curve for framework-specific concepts
  • - Can feel limiting for unusual use cases

Next Lesson

Next Lesson: Kotlin Essentials

  1. Basic syntax and data types
  2. Control flow (if, when, loops)
  3. Functions and lambdas
  4. Arrays and Collections
  5. Null safety

... and more!