Build Your Mobile App Backend in 15 Minutes

Difficulty: Beginner | Time: ~15 minutes | Target: Mobile developers evaluating Firebase alternatives

This tutorial walks you through setting up a production-ready backend for a mobile app using three open source services on Eyevinn Open Source Cloud:

  • PostgreSQL for relational data storage (user profiles, app data)
  • Valkey for session caching and real-time key-value storage
  • MinIO for file and image storage (S3-compatible)

At the end of this tutorial you will have all three services running and connection strings ready to paste into your iOS or Android app.

Prerequisites

  • An Eyevinn Open Source Cloud account. Sign up here for free.
  • A Personal or higher plan (running three simultaneous services requires a paid plan)

Step 1: Start a PostgreSQL Instance

PostgreSQL is where your app stores structured data: user profiles, app content, relationships between records.

  1. Go to app.osaas.io and open the Browse page
  2. Search for PostgreSQL and click the service card
  3. Subscribe to the service if you have not already done so
  4. Click Create instance and fill in the form:
  5. Name: myapp-db (or any name you choose)
  6. PostgresUser: appuser
  7. PostgresPassword: choose a strong password and note it down
  8. PostgresDb: appdb
  9. Click Create and wait for the status to show Running (usually under a minute)
  10. Click on the instance card to expand it and copy the host and port values

Your PostgreSQL connection details will look like this:

Host:     <your-tenant>-myapp-db.birme-osc-postgresql.auto.prod.osaas.io
Port:     5432
Database: appdb
User:     appuser
Password: <your-password>

Connection string:

postgresql://appuser:<YOUR_PASSWORD>@<YOUR_HOST>:5432/appdb

Step 2: Start a Valkey Instance

Valkey is a Redis-compatible key-value store. Use it for session tokens, caching API responses, and storing short-lived data that does not need to go into the database.

  1. On the Browse page, search for Valkey and click the service card
  2. Subscribe to the service if needed
  3. Click the Service Secrets tab and create a secret for your Valkey password:
  4. Click Create secret
  5. Give it a name, for example valkey-pwd
  6. Enter a strong password as the value
  7. Click the My valkeys tab and then Create valkey:
  8. Name: myapp-cache
  9. Password: select the secret you just created ({{secrets.valkey-pwd}})
  10. Click Create and wait for the status to show Running
  11. Note the IP address and port shown on the instance card once it is running

Your Valkey connection details will look like this:

Host:     <IP address shown on the instance card>
Port:     <port shown on the instance card>
Password: <the password you stored in the secret>

Connection string (Redis-compatible URL):

redis://:<YOUR_PASSWORD>@<YOUR_IP>:<YOUR_PORT>

Step 3: Start a MinIO Instance

MinIO provides S3-compatible object storage for images, files, and any binary content your app needs to store or serve.

  1. On the Browse page, search for MinIO and click the service card
  2. Subscribe to the service if needed
  3. Click Create objstorage and fill in the form:
  4. Name: myapp-storage
  5. RootUser: approot
  6. RootPassword: choose a strong password and note it down
  7. Click Create and wait for the status to show Running
  8. Click on the instance card to see the service URL

Your MinIO endpoint will look like this:

Endpoint: https://<your-tenant>-myapp-storage.minio-minio.auto.prod.osaas.io
AccessKey: approot
SecretKey: <your-root-password>

Create a bucket for your app's files. You can use the MinIO web console at https://<your-tenant>-myapp-storage.minio-minio.auto.prod.osaas.io (log in with your root credentials), or use the AWS CLI:

export AWS_ACCESS_KEY_ID=approot
export AWS_SECRET_ACCESS_KEY=<YOUR_ROOT_PASSWORD>
aws --endpoint-url https://<YOUR_MINIO_ENDPOINT> s3 mb s3://app-files

Step 4: Connect Your Mobile App

Use the connection details from steps 1 to 3 to configure your mobile app. The examples below use placeholder values, replace them with your actual values.

iOS (Swift)

PostgreSQL with PostgresClientKit:

import PostgresClientKit

var configuration = PostgresClientKit.ConnectionConfiguration()
configuration.host = "<YOUR_HOST>"
configuration.port = 5432
configuration.database = "appdb"
configuration.user = "appuser"
configuration.credential = .md5Password(password: "<YOUR_PASSWORD>")
configuration.ssl = true

let connection = try PostgresClientKit.Connection(configuration: configuration)

Valkey / Redis with RediStack:

import RediStack
import NIO

let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
let client = try RedisConnection.make(
    configuration: try .init(
        hostname: "<YOUR_IP>",
        port: <YOUR_PORT>,
        password: "<YOUR_PASSWORD>"
    ),
    boundEventLoop: eventLoopGroup.next()
).wait()

MinIO / S3 with the AWS SDK for Swift:

import AWSS3

// Configure the S3 client with your MinIO endpoint
// Set the endpoint override to your MinIO instance URL
// Use "approot" as the access key and your root password as the secret key
let s3Config = try await S3Client.S3ClientConfiguration(region: "us-east-1")

For MinIO with the AWS Swift SDK, set the custom endpoint to your MinIO instance URL and use approot as the access key.

Android (Kotlin)

PostgreSQL with JDBC:

import java.sql.DriverManager

val url = "jdbc:postgresql://<YOUR_HOST>:5432/appdb"
val props = java.util.Properties().apply {
    setProperty("user", "appuser")
    setProperty("password", "<YOUR_PASSWORD>")
    setProperty("ssl", "true")
}
val connection = DriverManager.getConnection(url, props)

Run database calls on a background thread (Coroutines or RxJava) to avoid blocking the main thread.

Valkey / Redis with Jedis:

import redis.clients.jedis.Jedis

val jedis = Jedis("<YOUR_IP>", <YOUR_PORT>)
jedis.auth("<YOUR_PASSWORD>")

// Store a session token
jedis.setex("session:user123", 3600, "token-value-here")

// Retrieve it
val token = jedis.get("session:user123")

MinIO / S3 with the AWS SDK for Android:

import com.amazonaws.auth.BasicAWSCredentials
import com.amazonaws.regions.Region
import com.amazonaws.services.s3.AmazonS3Client
import com.amazonaws.services.s3.S3ClientOptions

val credentials = BasicAWSCredentials("approot", "<YOUR_ROOT_PASSWORD>")
val s3Client = AmazonS3Client(credentials)
s3Client.setRegion(Region.getRegion("us-east-1"))
s3Client.setEndpoint("https://<YOUR_MINIO_ENDPOINT>")
s3Client.setS3ClientOptions(
    S3ClientOptions.builder().setPathStyleAccess(true).build()
)

// Upload a file
s3Client.putObject("app-files", "profile/user123.jpg", File("/path/to/image.jpg"))

Step 5: Test the Setup

Before wiring everything into your app, verify that each service is reachable.

Test PostgreSQL

psql "postgresql://appuser:<YOUR_PASSWORD>@<YOUR_HOST>:5432/appdb" -c "SELECT version();"

You should see the PostgreSQL version string. If you get a connection error, double-check the host, port, and password on the instance card in the OSC web console.

Test Valkey

export REDISCLI_AUTH=<YOUR_PASSWORD>
redis-cli -h <YOUR_IP> -p <YOUR_PORT> PING

Expected response: PONG

Test MinIO

export AWS_ACCESS_KEY_ID=approot
export AWS_SECRET_ACCESS_KEY=<YOUR_ROOT_PASSWORD>
aws --endpoint-url https://<YOUR_MINIO_ENDPOINT> s3 ls

You should see the app-files bucket listed.

What You Have Built

You now have a complete backend stack running on open source infrastructure:

Service Purpose Protocol
PostgreSQL Relational data storage JDBC / libpq
Valkey Session cache and key-value store Redis protocol
MinIO File and image storage S3 API

All three services run on Eyevinn Open Source Cloud without any vendor lock-in. You can move them to your own infrastructure at any time because they are standard open source projects.

Next Steps