English
MinIO High-Performance Object Storage Explained: Go Language Implementation and Cloud-Native Architecture

1. What is MinIO?
MinIO is a high-performance object storage service implemented in Go and fully compatible with the S3 protocol. It uses the GNU AGPL v3 open source license, and the project address is https://github.com/minio/minio, the official website is https://min.io.
You can think of it as an AWS S3 that can be deployed on your own servers, but it is more than that—it is becoming the de facto standard in private cloud, edge computing, and AI data lake scenarios. In China, companies such as Alibaba, Tencent, Baidu, Huawei, China Mobile, and China Unicom are all using MinIO, and even many commercial companies offer commercialized cloud storage products based on secondary development of MinIO.
2. What problem does it solve?
Before MinIO emerged, enterprises and developers typically faced the following pain points when handling unstructured data (images, videos, logs, backups, etc.):
Public cloud costs and lock-in: Long-term use of public cloud storage such as AWS S3 incurs high bandwidth and API request costs, and data migration is difficult, making it easy to be locked in by vendors.
Traditional storage has poor scalability.: 传统的 NAS 或 SAN 存储在处理海量小文件(如电商缩略图、IoT 传感器数据)时,元数据管理压力巨大,性能瓶颈明显。
Bloated architecture Unified storage systems like Ceph are powerful, but deployment and operations and maintenance are extremely complex, making them overly cumbersome for scenarios that only require object storage.
MinIO's value proposition: It allows enterprises to build a cost-controlled storage infrastructure in private data centers, public clouds, or edge nodes, with performance comparable to or even surpassing public clouds and seamlessly integrated with the S3 ecosystem, while breaking vendor lock-in.
3. Core Feature Breakdown
MinIO is not just a simple storage server; its design philosophy is full of the ingenuity of modern distributed systems.
3.1 The Underlying Secret of Ultimate Performance
MinIO's performance is not accidental, but the result of layer-by-layer optimization from the underlying hardware to upper-layer applications:
Go language advantages: The Go language's inherent concurrency model (Goroutine) and high-performance networking library enable MinIO to easily handle millions of concurrent connections.
Metadata-free single point: This is one of MinIO's most core designs. Traditional storage systems (such as HDFS or older versions of Ceph) rely on independent metadata nodes. When the number of small files explodes, metadata nodes become a performance bottleneck. MinIO stores metadata directly together with data files (
xl.meta), completely eliminating this bottleneck.Erasure Coding and Optimization: By default, erasure coding (Erasure Code) is used instead of multiple replicas, for example
8+4This mode requires only 1.5x storage space to achieve higher reliability than 3 replicas (tolerating 4 corruptions).Optimization for small objects: Traditional S3 gateways perform poorly when handling large numbers of small files. MinIO stores objects smaller than 128KiB directly inline in metadata files, reducing disk IOPS consumption and greatly improving performance in scenarios involving massive numbers of small files, such as AI/ML.
3.2 100% S3 Compatibility
This is MinIO's killer feature. It fully implements the core parts of the AWS S3 API. This means:
Seamless migration: You can develop code on your laptop using MinIO, then seamlessly deploy it directly to AWS S3 without changing a single line of code.
Ecosystem reuse: All tools in the S3 ecosystem (such as
aws-cli,s3cmd,Velero,Rclone)and data analysis engines (such as Spark, Presto) can directly connect to MinIO.
3.3 Cloud-Native Design
MinIO is tailor-made for Kubernetes:
Containerization first: Official Docker images are available, with an extremely simple startup command.
Operator support: With the MinIO Operator, you can achieve automatic scaling, rolling updates, and failure self-healing for clusters in K8s.
Portability: Supports unified deployment across on-premises, private cloud, public cloud (AWS, Azure, GCP), and edge computing nodes.
4. Quick Start: Deployment and SDK Initialization
4.1 Docker Deployment
Run the following command to start the MinIO service with one click:
bash
docker run -p 9000:9000 -p 9001:9001 \
-e "MINIO_ROOT_USER=minioadmin" \
-e "MINIO_ROOT_PASSWORD=minioadmin" \
minio/minio server /data --console-address ":9001"After successful startup, you will see output similar to the following:
log
INFO: Formatting 1st pool, 1 set(s), 1 drives per set.
INFO: WARNING: Host local has more than 0 drives of set. A host failure will result in data becoming unavailable.
MinIO Object Storage Server
Copyright: 2015-2026 MinIO, Inc.
License: GNU AGPLv3 - https://www.gnu.org/licenses/agpl-3.0.html
Version: RELEASE.2025-09-07T16-13-09Z (go1.24.6 linux/amd64)
API: http://172.17.0.2:9000 http://127.0.0.1:9000
WebUI: http://172.17.0.2:9001 http://127.0.0.1:9001
Docs: https://docs.min.io
WARN: Detected default credentials 'minioadmin:minioadmin', we recommend that you change these values with 'MINIO_ROOT_USER' and 'MINIO_ROOT_PASSWORD' environment variablesOutput interpretation:
| Output content | meaning |
|---|---|
Formatting 1st pool | Initialize the storage pool; currently in single-node single-disk mode. |
Version: RELEASE.2025-09-07... | Currently running MinIO version and Go version information |
API: http://127.0.0.1:9000 | S3 API service endpoint (for SDK and tool calls) |
WebUI: http://127.0.0.1:9001 | Web Management Console Address |
WARN: Detected default credentials | ⚠️ Security warning: default password in use,Be sure to replace it in the production environment. |
Visit http://localhost:9001, using username minioadmin/ password minioadmin Log in to the Web management console to get started.
4.2 Install the Go SDK
bash
go get github.com/minio/minio-go/v74.3 Obtain Access Credentials (Access Key & Secret Key)
MinIO uses Access Key / Secret Key for API access authentication. In the MinIO Community Edition, credential management is performed through the command-line tool mc Complete:
Method 1: Use administrator credentials directly (local testing only)
bash
# The administrator account set when Docker starts
-e "MINIO_ROOT_USER=minioadmin" # ← Access Key
-e "MINIO_ROOT_PASSWORD=minioadmin" # ← Secret Keygo
// Use in the Go SDK
accessKeyID := "minioadmin"
secretAccessKey := "minioadmin"⚠️ This method is only recommended for local development and testing; for production environments, be sure to use separate credentials.
Method 2: Through mc Create dedicated credentials via the command line (recommended for production)
bash
# 1. Install mc
brew install minio/stable/mc
# 2. Configure aliases
mc alias set myminio http://localhost:9000 minioadmin minioadmin
# 3. Create a new user (generate Access Key / Secret Key)
mc admin user add myminio myappuser myappsecret123
# 4. Assign permission policy
mc admin policy attach myminio readwrite --user=myappusergo
// Use newly created credentials in Go SDK
accessKeyID := "myappuser"
secretAccessKey := "myappsecret123"Safety tips: For local development and testing, the administrator account and password can be used directly as credentials. But Strongly recommended for production environments Create independent, permission-restricted access keys for different applications, follow the principle of least privilege, and avoid the risks caused by root key leakage.
4.4 Initialize Client
go
package main
import (
"context"
"log"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
)
func main() {
// ⚠️ Credential source: MINIO_ROOT_USER and MINIO_ROOT_PASSWORD in the Docker startup command
// For local testing, you can write it directly; in production, always use environment variables!
endpoint := "127.0.0.1:9000"
accessKeyID := "minioadmin" // ← Corresponds to MINIO_ROOT_USER
secretAccessKey := "minioadmin" // ← Corresponds to MINIO_ROOT_PASSWORD
useSSL := false // SSL is not enabled for local deployment.
// Initialize the client (recommended to reuse this Client instance)
minioClient, err := minio.New(endpoint, &minio.Options{
Creds: credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
Secure: useSSL,
})
if err != nil {
log.Fatalln(err)
}
log.Println("MinIO Client initialized successfully")
}5. Go SDK Practical Operations
5.1 Storage Bucket Management
go
// Create storage bucket
func createBucket(client *minio.Client, bucketName string) error {
ctx := context.Background()
err := client.MakeBucket(ctx, bucketName, minio.MakeBucketOptions{
Region: "us-east-1",
})
if err != nil {
// Check whether the bucket already exists
exists, errExists := client.BucketExists(ctx, bucketName)
if errExists == nil && exists {
log.Printf("Bucket %s already exists\n", bucketName)
return nil
}
return err
}
log.Printf("Bucket %s created successfully\n", bucketName)
return nil
}5.2 File Upload (Resumable Upload Supported)
go
func uploadFile(client *minio.Client, bucketName, objectName, filePath string) error {
ctx := context.Background()
// FPutObject automatically handles multipart upload for large files
info, err := client.FPutObject(ctx, bucketName, objectName, filePath, minio.PutObjectOptions{
ContentType: "application/octet-stream",
// For large files, the chunk size can be set.
PartSize: 64 * 1024 * 1024, // 64MB
})
if err != nil {
return err
}
log.Printf("Upload successful: %s, size: %d bytes\n", objectName, info.Size)
return nil
}5.3 File Download
go
func downloadFile(client *minio.Client, bucketName, objectName, localPath string) error {
ctx := context.Background()
object, err := client.GetObject(ctx, bucketName, objectName, minio.GetObjectOptions{})
if err != nil {
return err
}
defer object.Close()
localFile, err := os.Create(localPath)
if err != nil {
return err
}
defer localFile.Close()
if _, err = io.Copy(localFile, object); err != nil {
return err
}
log.Printf("Download successful: %s\n", localPath)
return nil
}6. Advanced Features in Practice
6.1 Presigned URL (Temporary Sharing)
go
func generatePresignedURL(client *minio.Client, bucketName, objectName string) (string, error) {
ctx := context.Background()
// Generate a download link valid for 7 days
presignedURL, err := client.PresignedGetObject(ctx, bucketName, objectName,
time.Hour*24*7, nil)
if err != nil {
return "", err
}
return presignedURL.String(), nil
}6.2 Bucket Event Listening
go
func listenBucketEvents(client *minio.Client, bucketName string) {
ctx := context.Background()
// Listen for upload and delete events
events := []string{
"s3:ObjectCreated:*",
"s3:ObjectRemoved:*",
}
for event := range client.ListenBucketNotification(ctx, bucketName, "", "", events) {
if event.Err != nil {
log.Printf("listening error: %v\n", event.Err)
continue
}
log.Printf("Received event: %s, object: %s\n",
event.Records[0].EventName,
event.Records[0].S3.Object.Key)
}
}6.3 Batch Operations and Concurrency Control
go
func batchUploadFiles(client *minio.Client, bucketName string, filePaths []string) error {
var wg sync.WaitGroup
errChan := make(chan error, len(filePaths))
// Limit the concurrency to 10
sem := make(chan struct{}, 10)
for _, filePath := range filePaths {
wg.Add(1)
go func(path string) {
defer wg.Done()
sem <- struct{}{}
defer func() { <-sem }()
objectName := filepath.Base(path)
if err := uploadFile(client, bucketName, objectName, path); err != nil {
errChan <- err
}
}(filePath)
}
wg.Wait()
close(errChan)
// Collect errors
var errors []error
for err := range errChan {
errors = append(errors, err)
}
if len(errors) > 0 {
return fmt.Errorf("batch upload failed: %v", errors)
}
return nil
}7. Production Environment Best Practices
7.1 Performance Optimization Recommendations
| Optimization item | Suggestion | Explanation |
|---|---|---|
| Reuse Client | global singleton | minio.Client It is concurrency-safe and avoids frequently creating connections. |
| Adjust shard size | Large files use 64MB+ chunks. | Reduce the number of network round trips |
| Set timeout | Passing a Context with a timeout | Avoid Goroutine leaks and resource usage. |
| connection pool | Adjust Transport Configuration | Increase the maximum number of idle connections |
| Compressed transmission | Enable gzip compression | Reduce network bandwidth consumption |
go
// Custom Transport configuration
func createCustomClient(endpoint, accessKey, secretKey string) (*minio.Client, error) {
// Custom HTTP Transport
transport := &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 100,
IdleConnTimeout: 90 * time.Second,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: false,
},
}
return minio.New(endpoint, &minio.Options{
Creds: credentials.NewStaticV4(accessKey, secretKey, ""),
Secure: true,
Transport: transport,
})
}7.2 Error Handling and Retry Mechanism
go
func uploadWithRetry(client *minio.Client, bucketName, objectName, filePath string,
maxRetries int) error {
var err error
for i := 0; i < maxRetries; i++ {
err = uploadFile(client, bucketName, objectName, filePath)
if err == nil {
return nil
}
log.Printf("Upload failed (attempt %d/%d): %v, retrying...\n", i+1, maxRetries, err)
time.Sleep(time.Duration(i+1) * time.Second) // backoff strategy
}
return fmt.Errorf("Upload failed after %d retries: %w", maxRetries, err)
}8. Cloud-native architecture: Kubernetes deployment
8.1 Deploy with Helm
bash
# Add the MinIO Helm repository
helm repo add minio https://charts.min.io/
helm repo update
# Deploy MinIO
helm install my-minio minio/minio \
--set rootUser=minioadmin \
--set rootPassword=minioadmin \
--set persistence.size=100Gi \
--set mode=standalone8.2 Deploying a production cluster using Operator
yaml
# minio-cluster.yaml
apiVersion: minio.min.io/v2
kind: Tenant
metadata:
name: my-minio-tenant
spec:
image: minio/minio:latest
imagePullPolicy: IfNotPresent
# 4-node cluster
pools:
- servers: 4
volumesPerServer: 4
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Ti
# credential
credsSecret:
name: minio-creds
# Enable console
console:
replicas: 2
consoleSecret:
name: console-secret9. Embracing the AI Era: Storage Is Understanding
MinIO is evolving into a data platform for AI/ML workloads. MinIO is not just an object storage; it is essentially becoming a key-value database, can simultaneously process unstructured data and structured tabular data:
表格数据支持: MinIO is elevating the Iceberg table format to a first-class citizen, directly supporting the storage and querying of structured data.
promptObject API: This is a revolutionary feature extension that allows you to directly "ask questions" about objects in storage (such as an image of a restaurant receipt): "What is the amount on this receipt?", and the backend runs a multimodal large language model to return the answer.
10. Summary
| dimension | Advantages of MinIO |
|---|---|
| performance | Go implementation, no metadata bottleneck, erasure coding optimization, small object inline storage |
| Compatibility | 100% S3 API compatible, seamlessly integrated with ecosystem tools |
| cloud-native | Container-first, K8s Operator, autoscaling |
| Development experience | A concise Go SDK, rich APIs, and comprehensive documentation. |
| AI ready | Iceberg support, promptObject API, data lake capabilities |
With its ultimate performance, pure S3 compatibility, and cloud-native DNA, MinIO has become the de facto standard for enterprise private cloud storage. For Go developers,minio-go With its concise interface and complete coverage of the S3 ecosystem, the SDK enables us to handle massive amounts of cloud data just like operating a local file system.
Whether you're building the next-generation data lake, hosting AI training datasets, or simply providing image storage for your web app, the MinIO + Go combination delivers a rock-solid technical foundation.
📌Related resources: