
<div class="callout callout-attn"><p><strong>Alpha software.</strong> Via is still early. Commands, config files, deploy behaviour, and host requirements may change between releases. Use it for test deployments while the platform settles.</p></div>

It is still early days for Via. We are exploring what the application server should look like for Vary apps, which parts should be platform-owned, and which interfaces should stay small enough for developers and operators to trust.

Vary has spent most of its life focused on the language: readable syntax, static types, contracts, code generation, mutation testing, and enough tooling to make a small service feel solid before it leaves a laptop.

That still leaves the awkward next question.

Where does the app run?

[Via](/docs/via/) is the answer we are building for that question. It is the application server for Vary apps. A developer gives Via committed source. Via checks it, builds it, signs the artifact, starts the runtime, attaches declared resources, publishes approved routes, and keeps a record of what happened.

Vary apps do not need Via. They compile to JVM artifacts, so they can run anywhere Java runs: a laptop, a VM, a container, a CI job, or an existing Java hosting setup. That portability is intentional.

Via is the other half of the idea. Vary should be portable, but it should also have an easy place to land when you do not want to design the whole operating path yourself.

The short version:

```bash
vary app deploy echo --target prod
```

That command should be the developer-facing shape. The platform can use Git, builders, runners, certificates, config profiles, add-ons, and proxy reloads behind the scenes. The person deploying the app should not have to assemble those pieces by hand every time.

## The problem

A Vary app is not useful because it compiled once. It becomes useful when it is running somewhere that an operator can trust.

That means the deployment path has to answer ordinary but stubborn questions:

| Question | Via's job |
|---|---|
| What source is running? | Receive committed source and record the resolved commit. |
| Was it checked? | Run the compiler and tests in a clean build environment. |
| What artifact started? | Package and sign the server-built artifact. |
| What config did it get? | Attach versioned config, secrets policy, and add-on descriptors. |
| Who can reach it? | Attach only routes that pass domain and host policy. |
| What happened when it failed? | Keep deploy states, logs, and audit records. |

None of those jobs are glamorous. That is partly the point. They are the jobs that become painful when every app does them differently.

## The split

Via has two command surfaces.

Operators use `via` on the host. They install the platform, initialize the domain, create users, create apps, define route policy, manage certificates, and inspect host health.

Developers use `vary` from a workstation. They log in, point at a target, preflight an app, deploy source, check status, read logs, and run smoke checks.

Keeping those surfaces separate matters. The operator should not need the app source on the host. The developer should not need host shell access to deploy. The platform sits between them and turns a source submission into an auditable release.

## The release path

The path is deliberately boring:

```mermaid
flowchart TB
    SOURCE[Committed source]
    CHECKOUT[Clean checkout]
    TESTS[Typecheck and test]
    ARTIFACT[Signed artifact]
    RUNTIME[Runtime launch]
    BINDINGS[Config and add-on bindings]
    ROUTES[Validated routes]
    OBSERVE[Status and logs]

    SOURCE --> CHECKOUT
    CHECKOUT --> TESTS
    TESTS --> ARTIFACT
    ARTIFACT --> RUNTIME
    RUNTIME --> BINDINGS
    BINDINGS --> ROUTES
    ROUTES --> OBSERVE
```

If the build fails, the release fails. If the route is not allowed, the route does not attach. If an older deploy is healthy, a broken new deploy should not replace it. That sounds obvious, but it is the kind of obvious behaviour that has to be designed into the platform from the start.

Vary already pushes people toward explicit contracts in code. Via tries to do the same thing for the release around that code.

## What Via owns

Via owns the parts that need a single source of truth.

It owns app identity, deploy operations, routes, domains, config profiles, secret delivery, add-on bindings, runtime status, and audit records. The builder owns clean builds. The runner owns verified runtime launch. The proxy owns public traffic after policy checks pass.

The app still owns its code. That boundary is important. Via should not turn a Vary app into a pile of platform-specific callbacks. The app declares what it needs. Via decides whether those declarations can become a release on this host.

[Managed SQLite](/docs/via/managed-sqlite/) is a good example. The app asks for a named SQLite binding. Via owns the database file, the binding descriptor, and the operational work around backup and restore. The app reads a binding, not a hard-coded path on someone else's server.

[Routes](/docs/via/domains-and-routes/) work the same way. The app can declare a hostname and path. Via checks whether the host allows that domain, whether proof is required, whether certificates are ready, and whether the route conflicts with another app. A deploy and a route change are related, but they are not the same risk.

## Why now

Vary is getting more server-shaped. Typed HTTP services, generated resources, declarative persistence, managed bindings, and smoke tests all point in the same direction: a Vary app should be more than a jar someone launches by hand.

That does not mean Via needs to be huge. The first useful version can be small. One host. One app. One deploy. One route. One clear status command.

But the shape has to be right.

The developer path should feel like this:

```bash
vary target add prod https://example.com
vary login --target prod --name alice
vary app preflight echo --target prod --apply-manifest
vary app deploy echo --target prod
vary app smoke echo --target prod
```

The operator path should stay equally direct:

```bash
via install
via init --domain example.com
via doctor
via app ensure echo --owner alice
via domain add echo.example.com --scope app --allowed-app-route-policy allow
```

There will be more policy later. More add-ons. More runtime options. More failure cases. The first job is simpler: make the happy path honest, make failures readable, and make the next command obvious.

## Where this goes next

Via is still alpha software, so the details will move. The purpose should not.

Vary apps need a place where source becomes a checked, signed, running service with routes, config, logs, and resource bindings attached by the platform. Via is that place.

The next article looks at the older platform that made this kind of workflow feel normal: Heroku.
