While building the backend, developers are often involved with a lot of repetitive tasks like configuring APIs, handling service discovery and scaling infrastructure.
What if you could automate most of these complex problems?
Today, we will learn about 10 common backend tasks and how to automate them using Encore.
Let's jump in.
Building scalable apps with cloud services often comes with a poor Developer Experience where Developers end up managing complex infrastructure and doing repetitive tasks, slowing them down.
Encore helps to solve that problem by offering an open source backend framework (for TypeScript and Go) that lets you define infrastructure as type-safe objects in your app, unifying your infra with your application code.
✅ High-performance Rust runtime
✅ No DevOps experience required
✅ Improved type-safety for distributed systems
If you're interested in reading about how the backend framework works behind the scenes using Encore’s multi-threaded Rust runtime, read the docs.
By the way, Encore is open source with 9.4k stars on GitHub.
Let's discuss points in detail.
1. API communication.
API Communication
is how different apps talk to each other and share information using an API (Application Programming Interface).
It’s like ordering food at a restaurant, your request (order
) goes to the kitchen (server
) and the kitchen sends back your food (response
).
In microservices, making reliable API calls is tricky. Developers often need to write HTTP clients manually among other things.
🎯 How Encore automates this?
With Encore, you don’t need to manually set up HTTP requests between services. Instead, API communication between services is achieved by treating API calls as regular function calls. No HTTP clients, no custom retry logic.
This gives you a simple monolith-like developer experience, even when you use multiple services. The only thing you need to do is import the service you want to call from ~encore/clients
and then call its API endpoints like functions.
You get all the benefits of function calls like:
✅ compile-time checking of all the parameters.
✅ auto-completion in your editor.
✅ allowing the division of code into logical components, services and systems.
In the example below, we import the service hello
and call the ping
endpoint using a function call to hello.ping
.
import { hello } from "~encore/clients"; // import 'hello' service
export const myOtherAPI = api({}, async (): Promise<void> => {
const resp = await hello.ping({ name: "World" });
console.log(resp.message); // "Hello World!"
});
If you're interested to know, read more on docs about API calls.
With Encore, API communication feels just like calling a function inside the same codebase.
2. Service discovery.
In a microservices architecture, service discovery
enables services to automatically locate and communicate with each other, even when their locations change dynamically (when a service moves or scales up/down).
Unlike monolithic systems, where all components exist in one place, microservices run independently, usually on different servers or containers.
Example: On a social media platform, when a user posts a new update, the platform needs to notify followers across different services (notifications, analytics,..). If a service moves or restarts, other services need to rediscover it in real time.
Manually managing these dependencies can lead to configuration errors and downtime.
If you're interested in reading more, What is Service Discovery? Complete guide - 2025 Edition by Middleware is a great place to start.
🎯 How Encore automates this?
Encore improves service discovery by generating boilerplate code and automatically setting up the necessary infrastructure resources. It also improves the developer experience (DX) by providing Service Catalog and API documentation.
Instead of maintaining service registries or hardcoding dependencies, Encore uses the Encore Application Model to automatically generate a Service Catalog by tracking all available services and their endpoints.
You can find it in the local development dashboard.
You can see a summary of all your services, view details of a specific service and see the type of endpoints that service has. If you've added comment descriptions to your code, it will also be shown accordingly.
While viewing the details of an endpoint, you can see the request and response objects. You can even call it directly from the service catalog.
Plus, you can copy it as cURL if you need to call it from the terminal.
You can watch this video to understand more.
3. Architecture diagrams.
In a microservices architecture, understanding how services interact is important for debugging, scaling and optimizing performance. Usually, teams create and maintain architecture diagrams manually, but they become outdated as the system evolves.
For example, in an uptime monitoring system, various services handle status checks, notifications and analytics. A real-time architecture diagram would make it much easier to track how these services connect and respond to incidents.
🎯 How Encore automates this?
An always up-to-date architecture diagram helps engineers quickly identify service dependencies, potential bottlenecks and the flow of data across the system.
Encore provides a visual tool known as Flow
that gives you an always up-to-date view of your entire system, helping you reason about your microservices architecture and identify which services depend on each other and how they work together.
✅ Track down bottlenecks before they grow into big problems.
✅ Instantly reveal the nature and scale of its dependencies.
✅ Auto update in real-time to reflect your architecture as you make code changes.
It is accessible in the Local Development Dashboard and the Encore Cloud dashboard for cloud environments.
When developing locally, Flow will auto-update in real time to reflect your architecture as you make code changes. For cloud environments, it auto-updates with each deployment.
In the example below the login
service has dependencies on the user
and authentication
services. Dashed arrows show publications or subscriptions to a topic. Here, payment
publishes to the payment-made
topic and email
subscribes to it.
As I said before, it updates in real time. In the example below a new subscription on the topic payment-made
is introduced and then removed in the user
service.
You can hover over a service, or PubSub topic, to instantly reveal the nature and scale of its dependencies.
From the below diagram, we can notice that login
makes queries to the database and requests to two of the endpoints from the user
service as well as requests to one endpoint from the authentication
service.
Let's say we are building an uptime monitoring system that notifies you when your website goes down so you can fix it before your users notice.
Here is the automatically generated diagram of the backend architecture, where white boxes are services and black boxes are Pub/Sub topics.
You can watch this video to understand more.
4. Infrastructure provisioning for local and cloud environments.
Infrastructure provisioning
is the process of setting up and managing the IT resources needed for an application to run, such as servers, databases and networks.
Developers often need to configure cloud resources like databases, message queues and API gateways manually.
For example, if you're building a real-time chat application, you need to provision a database, a WebSocket server and a load balancer. Managing these components manually across different environments (development, staging, production) adds extra overhead.
Infrastructure automation
is using tools to manage and provision these automatically. Tools like Terraform or AWS CloudFormation let you define your infrastructure as code (IaC).
With IaC, you can spin up identical environments for development, testing, and production with just one command. Pulumi is one such modern IaC tool that uses programming languages you already know, like JavaScript or Python.
But using IaC, you still have to manually write thousands of lines of terraform code to automate infra, which is a lot of work.
🎯 How Encore automates this?
Encore lets you define infrastructure as type-safe objects in your app, unifying your infra with your application code. Encore can then automate the infrastructure provisioning by parsing the application code.
// Define a PostgreSQL database in one line of code
import { SQLDatabase } from "encore.dev/storage/sqldb";
const db = new SQLDatabase("userdb", {migrations: "./migrations"});
// ... use db.query to query the database.
Encore Cloud automatically provisions all necessary infrastructure, in all environments and across all major cloud providers, without requiring application code changes.
✅ Works across cloud providers without vendor lock-in.
✅ No need to write Terraform or manage cloud-specific configurations.
The approach is to combine an open source backend development framework, with a SaaS based platform for cloud automation (Encore Cloud
). This combination provides PaaS-like deployment simplicity and powerful developer productivity features, while maintaining the flexibility of running everything in your own cloud account (AWS/GCP).
Below is the architecture diagram to help you understand how it works behind the scenes.
Like PaaS
, it fully automates infrastructure and cloud deployment.
Like IaC
, it allows you to use your own cloud provider and powerful infrastructure services like Kubernetes, but without any of the manual overhead and complexity of Terraform.
Unlike traditional PaaS, Encore Cloud doesn't host your applications. Your infrastructure stays in your own AWS or GCP account, so you never lose control.
Check out the docs to learn about automating infrastructure provisioning.
There is also an interesting blog on Designing an algorithmic cloud infrastructure provisioning system by the Encore team.
5. DevOps Automation.
DevOps automation provides clear and defined prescriptions for each stage of the software development life cycle. It improves CI/CD pipelines, deployment processes and monitoring tasks.
Consider a rapidly growing e-commerce platform experiencing frequent deployments and infrastructure changes. The DevOps team struggles to keep up with the manual provisioning of resources, configuration management and deployment processes. This could lead to inconsistencies, deployment failures and downtime.
Tools like Jenkins, GitHub Actions, or GitLab CI help in CI/CD. Also, Kubernetes handles container orchestration by managing your app’s scaling and load balancing on its own.
🎯 How Encore automates this?
Encore provides open source tools to help you integrate with your cloud infrastructure, handling deployment and monitoring.
Whether you’re self-hosting with Docker or using Encore Cloud, it fully automates provisioning and managing infrastructure in your own cloud on AWS and GCP.
This approach dramatically reduces the level of DevOps expertise required to use scalable, production-ready, cloud services like Kubernetes and Pub/Sub. And because your application code is the source of truth for infrastructure requirements, it ensures the infrastructure in all environments is always in sync with the application's current requirements.
Encore provides built-in DevOps tools:
✅ Infrastructure Tracking & Approvals workflow
✅ Automatic least privilege IAM
✅ Cost Analytics Dashboard
✅ Encore Terraform provider for extending infrastructure
So yeah, you practically need very little to no DevOps experience.
You can read more on the docs about DevOps automation.
6. API Documentation.
All developers agree API documentation is great to have, but the effort of maintaining it inevitably leads to docs becoming stale and out of date.
Imagine you’re integrating with an API, only to realize the documentation is outdated, endpoints are missing, request parameters don’t match and error codes are incorrect. This leads to frustration, wasted time debugging and unnecessary back-and-forth with the API provider.
Consider a public API for a social media platform where developers frequently add new features or modify existing endpoints. Manually updating the documentation each time takes longer and is prone to errors.
Keeping API documentation up-to-date is a common pain point for developers.
🎯 How Encore automates this?
With Encore’s Local Development Dashboard, API documentation is automatically generated for all your API endpoints.
The documentation updates dynamically as you modify your APIs.
This is powered by Encore’s static analysis, which processes your API definitions directly from your application code, making sure the documentation always stays up-to-date with the latest implementation.
It also provides an API Explorer for testing your APIs.
API documentation is part of the service catalog (which we covered in service discovery), but I kept this section separate since they cover different aspects.
7. Preview Environments.
Preview environments
represent individual, temporary deployments created for each PR. These are faithful replicas of your production environment that encompass all microservices, databases and dependencies.
It allows developers to test changes in isolated environments before merging them into the main branch.
However, setting them up manually often becomes a DevOps nightmare.
- Replicating production-grade infrastructure (databases, queues, APIs) for temporary environments requires deep cloud expertise.
- Seeding test data without leaking production data demands careful orchestration.
- Ensuring 1:1 alignment with production configurations (security rules, network policies) is error-prone.
Without preview environments, testing in shared staging risks breaking other features. But manually provisioning AWS resources (EC2, RDS, VPCs) for each PR would take days.
🎯 How Encore automates this?
When you're using Encore to build your backend application, the only setup needed to activate preview environments is to connect your GitHub account and you will immediately get the benefits of preview environments.
They are free, fully-managed development environments that run on Encore Cloud. Once connected to GitHub, pushing code will trigger deployments automatically.
You don't need to worry about orchestration, integration, cleanup or implementing any separate monitoring. It comes with built-in distributed tracing and instrumentation for key performance metrics.
It also automatically comes with pre-populated test data thanks to Neon's database branching feature. You can read more on the docs.
You can track the deployment progress in the Cloud Dashboard as well.
8. Observability.
Observability
, at a high level, is defined as the process of using external outputs to evaluate the internal state of a system.
Imagine your app goes viral overnight and traffic surges. At first, everything seems fine, until checkout requests start failing and users start reporting errors. Without proper observability, you will be left in the dark, struggling to pinpoint the issue.
Getting real-time insights and detailed records, so you can identify bottlenecks and debug faster will make your work a lot easier, especially during unexpected traffic.
If you're interested in learning more, A Guide to Observability Principles: Significance, Practical Implementations, and Best Practices is a good place to start.
🎯 How Encore automates this?
Encore provides built-in observability without any extra setup. It automatically tracks logs, traces, and metrics for all your backend services.
✅ Encore provides distributed tracing to track requests across your app and infrastructure.
As opposed to the intensive instrumentation you would normally need to go through to use tracing, Encore automatically captures traces for your entire application, in all environments. Uniquely, this means you can use tracing even for local development to help debug and speed up iterations.
You get access to a lot of information such as stack traces, structured logging, HTTP requests, network connection information, API calls, database queries and more. Read more on the docs.
✅ It provides automatic dashboards of common application-level metrics for each service.
It's also easy to define custom metrics for your app. Once defined, custom metrics are automatically displayed on the metrics page in the Cloud Dashboard.
You can also send your metrics to third-party services like Datadog, Grafana, instead of your cloud provider's monitoring service. Read the docs.
✅ Encore offers built-in support for Logging, which combines a free-form log message with structured and type-safe key-value pairs. It makes it easier for a computer to parse, analyze and index.
You just need to add it in the module: import log from "encore.dev/log";
.
Then you can call any of the logging functions such as error
, warn
, info
, debug
or trace
to emit a log message.
const logger = log.with({is_subscriber: true})
logger.info("user logged in", {login_method: "oauth"}) // includes is_subscriber=true
You can also live-stream your logs directly to your terminal by running: encore logs --env=prod
. Read more on the docs.
The local development dashboard combines all of these to automate observability. This way, developers can focus on what actually matters.
9. Validate incoming requests
API request validation
is the process of checking the alignment of client requests with the laid-out API specifications.
Without proper validation, your application might process incomplete or malicious data, leading to unexpected behavior, costly debugging or even exposing sensitive information.
For instance, in a payment processing API, incoming requests must include valid payment details like card number, expiry date, CVV. If these fields are missing or incorrectly formatted, things could go very wrong.
Validating such requests across multiple endpoints is important, but we can make the process easier.
🎯 How Encore automates this?
Encore.ts uses the natural TypeScript types directly to validate incoming requests, so you get the best of both worlds: the concise TypeScript syntax and runtime schema validation. This means your APIs are type-safe during both runtime and compile-time.
Encore.ts makes it easy to define API endpoints that combine data from different sources: some fields from the request body, others from the query parameters and some from the HTTP headers.
Here is an example.
import { Header, Query, api } from "encore.dev/api";
interface Request {
// Optional query parameter. Parsed from the request URL.
limit?: Query<number>;
// Custom header that must be set. Parsed from the HTTP headers.
myHeader: Header<"X-My-Header">;
// Required enum. Parsed from the request body.
type: "sprocket" | "widget";
}
export const myEndpoint = api<Request, Response>(
{ expose: true, method: "POST", path: "/api" },
async ({ limit, myHeader, type }) => {
// ...
},
);
You can read more on the docs about validating incoming requests including supported validation types and value-based rules.
🎯 Type Safe APIs.
Encore.ts also ensures type-safe APIs with zero extra setup. At its core, APIs in Encore.ts are normal async
functions with request and response data types defined as TypeScript interfaces.
⚡ It generates the necessary setup automatically, which means no boilerplate
.
⚡ It analyzes your code to detect request and response schemas, automatically validating incoming requests.
To define an API endpoint, we need to use the api
function from the encore.dev/api
module. Encore.ts then generates the necessary boilerplate at compile-time. Here is an example.
// inside the hello.ts file
import { api } from "encore.dev/api";
export const ping = api(
{ method: "POST" },
async (p: PingParams): Promise<PingResponse> => {
return { message: `Hello ${p.name}!` };
},
);
You can read more on the docs about Type-Safe APIs.
10. Database migrations.
Database migration
(also known as schema migration
) is the process of moving data, metadata and schema between databases.
Managing database schema changes across environments can be tough, especially when coordinating migrations with application updates.
Consider an e-commerce platform where you need to add a new column to the products
table to support product variants. Manually applying this change across development, staging and production environments might lead to problems and will definitely take longer time than usual.
If you're interested in reading more, check out what are database migrations by Prisma.
🎯 How Encore automates this?
Encore makes database migrations easier by treating SQL databases as logical resources and natively supporting PostgreSQL. It uses change-based
migrations.
✅ Encore automatically applies up
migrations. Each up
migration runs sequentially, expressing changes in the database schema from the previous migration.
✅ Down
migrations still need to be executed manually when rolling back changes.
✅ Encore maintains a schema_migrations
table that tracks applied migrations, which improves consistency across development, staging and production environments.
database=# \d schema_migrations
Table "public.schema_migrations"
Column | Type | Collation | Nullable | Default
---------+---------+-----------+----------+---------
version | bigint | | not null |
dirty | boolean | | not null |
Indexes:
"schema_migrations_pkey" PRIMARY KEY, btree (version)
✅ Encore supports popular ORMs (Prisma, Drizzle, Sequelize) and migration frameworks (Atlas). If your ORM or tool can connect to a database via a standard SQL driver or generate SQL migration files, it will work easily with Encore.
Example: SQLDatabase
allows you to create a named database and retrieve its connection string. This connection string can be used by your chosen ORM or migration framework to establish a database connection.
import { SQLDatabase } from "encore.dev/storage/sqldb";
// Initialize a named database with migration directory
const SiteDB = new SQLDatabase("siteDB", {
migrations: "./migrations",
});
// Retrieve the connection string for ORM use
const connStr = SiteDB.connectionString;
If a migration fails (let's say due to syntax errors or schema conflicts), Encore rolls back the migration and aborts the deployment.
Migration files are stored in a migrations
directory within the service package.
/my-app
├── encore.app // ... other top-level project files
│
└── todo // todo service
├── migrations // database migrations (directory)
│ ├── 1_create_table.up.sql // first migration file
│ └── 2_add_field.up.sql // second migration file
├── todo.ts // todo service code
└── todo.test.ts // tests for todo service
The first migration typically defines the initial table structure. When you run your application locally or deploy it to the cloud, Encore automatically applies all pending up
migrations in order.
Check out the docs for a step-by-step guide on database migrations, handling errors, connecting databases and more.
There are many more things you can do with Encore:
-
Automated testing
- built-in testing tools that make it simple to test your application using a variety of test runners. -
Automated IAM
- automates security best practices by generating least-privilege IAM policies from parsing your code. -
Deployment automation (Replay)
- Railway has no way of knowing that you've pushed a new image to the container registry, but Encore can use Railway's GraphQL API to trigger a new deployment whenever a new image is pushed to the registry.
I'm not covering all the topics to avoid making this very long, so check the docs for full details.
If you're planning to start using Encore, check out their SAAS starter template. It includes Next.js (frontend), Encore.ts (backend), Clerk (authentication), Stripe (payments), Tailwind and Shadcn (styling).
Whew! This was a lot to cover.
Backend development is very complex. I hope these will automate some of your repetitive work.
If you have any questions or feedback, please let me know in the comments.
Have a great day! Until next time :)
You can check my work at anmolbaranwal.com. Thank you for reading! 🥰 |
|
---|
Top comments (16)
This is a great breakdown of backend automation! Automating repetitive tasks is a huge productivity boost, and it's interesting to see how Encore streamlines so many aspects, from API communication to observability
This is one of the first tools that I've seen in the past few months that I actually might consider using. Pretty cool!
Awesome Oscar! I'm happy this was useful. I've been writing about Encore for quite a while :)
This is awesome!
Thanks for reading! 🔥
Ok, I may have to check out encore now.
I'm really glad it was useful. You can also read this if you need a step-by-step guide on how to start using it. I evaluated Encore based on type safety, performance, DX, scalability and extra benefits.
Thanks for reading, Zachary! 🔥
Good one, Anmol. 🙌
Thanks for reading Shrijal! Appreciate it. 🔥
Informative article, Anmol.
Thanks for checking this out, Bonnie! 🔥 Really appreciate it.
Nice explanation, @anmolbaranwal by the way the images and gif are created or you used some excalidraw type editor
Thanks Yash! The images are mostly from the docs. If I ever create something myself, it is mostly in Adobe XD (as I've been using it since college).
Still, I'm a fan of hand drawn styles in Excalidraw.
Cool!
This is not an article. It is an advertisement.
You might feel that way, but I've genuinely tried my best to provide as much value as possible. If you think there's anything that can be improved, please share your feedback and I will try to do better next time.