A different approach to developer tooling for startups
Tags: go, cloud, cloudnative, programming
Published: 2024-03-07 10:24:39

Yes, your team has the experience to put together a productive developer workflow (AKA developer platform).

Probably, you will be using a range of existing tools like Terraform, Helm, Docker Compose, various infrastructure emulators, CI/CD like Argo or CircleCI, etc.

Maybe, that even sounds like a fun challenge.

But, do you really have the time?

If you are trying to get a new business off the ground, building a new and exciting product, then NO you don't have the time.

99% of startups fail because they run out of money before they find product-market fit.

Putting together internal tooling does not help in that journey, it creates nothing new, and is of zero interest to your potential users and customers.

Even if you believe you do have time, is it a reasonable priority to spend months setting things up. Then keep spending a significant % of ongoing engineering time just to maintain it?

All for an end-result that is, AT BEST, riddled with manual steps and endlessly forcing developers to maintain the configuration of multiple environments.

This is the status quo we're trying change at [Encore](https://encore.dev).

## Our beliefs

- In order to make a meaningful improvement, you can't focus on improving only one specific area of the development process.

- Development experience and productivity is death by a thousand cuts — because all current tools focus on a narrow problem and desperately want to be compatible with all other tools out there.

- If you cannot control a significant part of the workflow, you can't make an order of magnitude improvement.

That's why Encore is designed to integrate the workflow from local development, through testing, all the way to cloud and DevOps.

## How it works

It all starts with your application code:

- Encore provides a Microservices Framework and Infrastructure SDK

- When you use it, it lets Encore understand your application's logical architecture AND its infrastructure requirements.

### Code Examples

#### **Defining a service**

With Encore you define a service by defining an API within a regular Go package. Encore recognizes this as a service, and uses the package name as the service name. When deploying, Encore will automatically [provision the required infrastructure](/docs/deploy/infra) for each service.

On disk it might look like this:

```
/my-app
├── encore.app          // ... and other top-level project files
│
├── hello               // hello service (a Go package)
│   ├── hello.go        // hello service code
│   └── hello_test.go   // tests for hello service
│
└── world               // world service (a Go package)
    └── world.go        // world service code
```


This means building a microservices architecture is as simple as creating multiple Go packages within your application.
See the [app structure documentation](/docs/develop/app-structure) for more details.

#### **Defining an API**

To define an API, add the `//encore:api` annotation any regular Go function.
This tells Encore that the function is an API endpoint. Encore will then automatically generate the necessary boilerplate at compile-time.

In the example below, we define the API endpoint `Ping`, in the `hello` service, which gets exposed as `hello.Ping`.

```go
package hello // service name

//encore:api public
func Ping(ctx context.Context, params *PingParams) (*PingResponse, error) {
    msg := fmt.Sprintf("Hello, %s!", params.Name)
    return &PingResponse{Message: msg}, nil
}
```

#### **Defining a Pub/Sub topic**

If you want a Pub/Sub Topic, you declare it directly in your application code, like so:

```go
import "encore.dev/pubsub"
 
type User struct { /* fields... */ }
 
var Signup = pubsub.NewTopic[*User]("signup", pubsub.TopicConfig{
  DeliveryGuarantee: pubsub.AtLeastOnce,
})
 
// Publish messages by calling a method
Signup.Publish(ctx, &User{...})
```

To run your application, you simply use `encore run`. Encore will automatically set up the local infrastructure and generate the boilerplate code necessary.
You also get a [local development dashboard with distributed tracing](/docs/observability/dev-dash) to help you understand and debug application behavior with ease.

Your code doesn't change when you want to deploy to the cloud. Encore will generate the necessary boilerplate and provision the necessary infrastructure in all environments:
- **NSQ** for local development
- **GCP Pub/Sub** for environments on GCP
- **SNS/SQS** for environments on AWS

## 💪 The result is very impactful

All this "understanding" Encore has about your application means it can automate many of the repetitive time-consuming activities that go into building modern backends:

- Generating boilerplate code for service discovery, APIs, authentication, database connection, etc.

- Instrumenting the application with tracing, logs, and metrics.

- Generating API documentation, a service catalog, and system architecture diagrams.

- Setting up the local development environment with local infrastructure for microservices, Pub/Sub, Databases, caches, secrets, etc.

- Setting up ephemeral cloud Preview Environments for each Pull Request for easy end-to-end testing.

- Provisioning infrastructure services and deploying to your cloud in AWS/GCP.

- Providing Cloud Cost Analytics.

- And much more.

## The limitations

Let's be clear, in order to accomplish all this, we've had to narrow our scope:

- Encore only supports Go, with TypeScript support being added shortly.
- Encore supports AWS and GCP, with Azure support coming later this year.

## 🕹 Try it yourself

- Learn more about building Go apps with Encore using [these Tutorials](https://encore.dev/docs/tutorials).👈
- Find inspiration on what to build with these [Open Source App Templates](https://encore.dev/templates).👈

## Wrapping up

- ⭐️ Support the project by [starring Encore on GitHub](https://github.com/encoredev/encore).
- If you have questions or want to share your work, join the developers hangout in Encore's [community on Discord](https://encore.dev/discord).