Learning objectives
After reading this article you will be able to:
- Build a production-ready JAR (Spring Boot) or published folder (.NET)
- Configure port and address by reading environment variables
- Verify the deploy and fix the most common port and memory errors
On this page
- What do you need before hosting?
- How do you create and build the API in Java with Spring Boot?
- How do you create and publish the API in .NET?
- Why does the API listen on 0.0.0.0 and read the port from the environment?
- How do you check that the deploy worked?
- What are the most common errors?
- How to do this on Square Cloud
- FAQs
A Java or .NET API usually works on your machine because it has the JDK or SDK, a free port and the right variables. In production three things change: you ship a compiled artifact instead of the source tree; the port comes from the environment; and the process must accept connections from outside the container.
This guide uses Spring Boot for Java and an ASP.NET Core Minimal API for .NET. The path is the same for both: build, make the port configurable, run locally the way production will, upload and verify. For the big picture on any API, see how to host an API.
What do you need before hosting?#
- Java: a JDK that meets the minimum for your Spring Boot version, per its system requirements. For a new project, use a current LTS of Java (Oracle's support roadmap). To build, a recent version of Maven or Gradle; the same page lists the minimum for each.
- .NET: the SDK for the current LTS of .NET. Microsoft's support policy shows which version that is and how long each one gets fixes.
- A health endpoint (
/health) to test the deploy without depending on a database or authentication. - A place to run it with the matching runtime. If you are still comparing options, see VPS vs cloud platform.
How do you create and build the API in Java with Spring Boot?#
Generate the project at start.spring.io with the Spring Web dependency. Here is the main class, with a health endpoint:
package com.example.demo;
import java.util.Map;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@GetMapping("/health")
public Map<String, String> health() {
return Map.of("status", "ok");
}
}In src/main/resources/application.properties, make the port configurable:
server.port=${PORT:8080}server.port=${PORT:8080}: reads thePORTvariable and falls back to8080when it is missing. The Spring Boot documentation also acceptsSERVER_PORTdirectly in the environment, thanks to relaxed binding. The framework default is 8080.- Shutdown: graceful shutdown is on by default in Spring Boot: when the stop signal arrives, the server finishes in-flight requests before exiting. No extra configuration is needed.
Build and run the JAR the way production will:
./mvnw -DskipTests package
PORT=9090 java -jar target/demo-0.0.1-SNAPSHOT.jar
curl http://localhost:9090/healthThe spring-boot-maven-plugin already comes in the generated project and packages an executable JAR with everything inside (a fat JAR). With Gradle the equivalent is ./gradlew bootJar. The file name comes from the artifactId and the version. Rename it to something short, such as app.jar, before uploading: that makes the main file easier to point to.
How do you create and publish the API in .NET?#
Create the project and replace Program.cs:
dotnet new web -n MyApi
cd MyApivar builder = WebApplication.CreateBuilder(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "8080";
builder.WebHost.UseUrls($"http://0.0.0.0:{port}");
var app = builder.Build();
app.MapGet("/health", () => Results.Ok(new { status = "ok" }));
app.Run();ASP.NET Core does not read the PORT variable on its own, so the code does it. Kestrel listens only on localhost by default, and 0.0.0.0 makes it accept connections from outside the container. The no-code alternative is to set ASPNETCORE_URLS=http://0.0.0.0:8080 in the environment.
Publish in Release mode and test the output folder:
dotnet publish -c Release -o out
PORT=9090 dotnet out/MyApi.dll
curl http://localhost:9090/healthWhat goes to the server is the contents of the out folder: the main DLL, its dependencies and the .json configuration files. Do not upload the bin and obj folders.
Why does the API listen on 0.0.0.0 and read the port from the environment?#
In a container or on a hosting platform, the server decides the port and the entry address, not your code. Listening on localhost (127.0.0.1) only accepts connections from inside the container itself, so the proxy in front never reaches your process. Hardcoding the port works only until the server asks for a different one. That is why both examples have a default for development and accept an override through an environment variable. To understand the concept, see what environment variables are.
Secrets such as connection strings and API keys follow the same rule: they come from the environment, never from the repository. In Spring Boot, DB_URL becomes ${DB_URL} in application.properties. In .NET, builder.Configuration["DB_URL"] already reads environment variables.
How do you check that the deploy worked?#
- Logs: look for the startup line with the configured port. In Spring:
Tomcat started on port 8080. In .NET:Now listening on: http://0.0.0.0:8080. - Health endpoint:
curl -i https://your-domain/healthshould return200and{"status":"ok"}. - Restart: restart the application and confirm it comes back up and that the logs show no requests cut off halfway.
- Memory: watch usage after a few requests. The JVM and the .NET runtime reserve memory beyond what your code uses, so the first measured value is usually higher than expected.
What are the most common errors?#
Port 8080 was already in use: another process holds the port, or the platform expects a different one. SetPORTand confirm the code reads it.- The app starts but the site does not open: the server listens on
localhost. In .NET, use0.0.0.0inUseUrls. no main manifest attribute, in app.jar: the JAR is not executable. Build with thespring-boot-maven-plugin(orbootJarin Gradle), not the default JAR plugin.UnsupportedClassVersionError: the JAR was compiled with a newer Java version than the runtime. Use the same version for the build and in production.The framework 'Microsoft.AspNetCore.App', version '10.0.0' (x64) was not found: the server does not have that version of the ASP.NET Core Runtime, or has one older than the project'sTargetFramework.OutOfMemoryErroror the process killed for lack of RAM: the allocated memory is lower than what the app needs. Increase the application's RAM before tuning JVM flags.
Before opening it to the public, go through the API production checklist.
How to do this on Square Cloud#
On Square Cloud the deploy is self-service: you build, upload and control everything. Java and .NET are among the platform's many runtimes, alongside Node.js, Python and Go; build the JAR with the same Java version as the runtime to avoid an UnsupportedClassVersionError. You can deploy with a ZIP in the dashboard, the CLI, GitHub (a push triggers the deploy) or the VS Code extension.
You set the main file in the dashboard or in squarecloud.app, which holds the name, main file, memory and version. squarecloud.app is optional: the dashboard generates it on deploy, and writing it at the project root is the alternative. Environment variables, such as the database connection string, are set per application, and a change applies on the next restart, with no rebuild. The platform sets PORT: the web application listens on 0.0.0.0 on that port, as in both examples. There is no build step on the platform, so upload the JAR or the published folder, or build in an external CI.
The application runs in an always-on container, with no sleep mode. With automatic restart (on by default for dashboard deploys), it comes back by itself when the process exits with an error. The plan's RAM is a pool shared across your applications, with a minimum of 512 MB for a web application. Every web application gets a *.squareweb.app subdomain with HTTPS, and custom domains are available from the Standard plan.
See how to host APIs on the APIs page, the runtimes on the runtimes page, and the REST API and official SDKs under SDKs.
API hosting
APIs in always-on containers, with no cold starts
FAQs
Which Java version should I use for a Spring Boot API?
Each Spring Boot version requires a minimum Java version, listed on the project's system requirements page. For a new project, pick a current LTS of Java and use the same version for the build and in production.
Which .NET version should I use in production?
Use the current LTS of .NET, which is supported the longest. Avoid starting a project on a version close to end of support: Microsoft's official support policy lists the dates for each one.
Do I need Maven or the dotnet SDK on the server?
Not necessarily. You can build on your machine or in CI and upload only the JAR or the published folder. The server only needs the runtime (a JRE or the ASP.NET Core Runtime).
My API starts but cannot be reached from outside. What should I check?
Check that it listens on 0.0.0.0 and not on localhost, and that the port is the one the server expects. ASP.NET Core's Kestrel listens only on localhost by default, and Spring Boot uses 8080 unless you set another port.
More in APIs
See all 15 articles- How to host an APIHosting an API means running its HTTP server around the clock at a public address with HTTPS. Step-by-step with Node.js and Python, testing and common errors.
- How to host a Node.js appTo host a Node.js app, prepare package.json, read the port and secrets from the environment, pick an LTS version and run it with node. Step-by-step guide.
- How to host a FastAPI, Flask or Django appTo host a FastAPI, Flask or Django app, run it with a production server (Uvicorn or Gunicorn) on 0.0.0.0. Commands, Django settings and common errors included.
- How to host a Python app or scriptTo host a Python app or script, pin the version, isolate dependencies in a venv, read secrets from the environment and handle SIGTERM. Step-by-step guide.