{"id":13393739,"url":"https://github.com/appleboy/gorush","last_synced_at":"2026-03-08T06:03:15.179Z","repository":{"id":37821004,"uuid":"54453471","full_name":"appleboy/gorush","owner":"appleboy","description":"A push notification server written in Go (Golang).","archived":false,"fork":false,"pushed_at":"2026-01-26T11:34:57.000Z","size":6004,"stargazers_count":8678,"open_issues_count":59,"forks_count":878,"subscribers_count":187,"default_branch":"master","last_synced_at":"2026-01-27T01:10:27.120Z","etag":null,"topics":["android","apns","gcm","golang","gorush-server","ios","ios-alert-payload","ios-notification","notification-server"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/appleboy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"appleboy","patreon":null,"open_collective":"gorush","ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":["https://www.paypal.me/appleboy46"]}},"created_at":"2016-03-22T07:15:20.000Z","updated_at":"2026-01-26T02:40:45.000Z","dependencies_parsed_at":"2023-02-17T14:46:04.617Z","dependency_job_id":"a56746d4-7496-4368-93f6-04f8684681fb","html_url":"https://github.com/appleboy/gorush","commit_stats":{"total_commits":939,"total_committers":55,"mean_commits":"17.072727272727274","dds":0.09691160809371668,"last_synced_commit":"2c3391e58a4f711dee9caa87dfc9e7f6d1d4166c"},"previous_names":["appleboy/gopush"],"tags_count":52,"template":false,"template_full_name":null,"purl":"pkg:github/appleboy/gorush","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appleboy%2Fgorush","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appleboy%2Fgorush/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appleboy%2Fgorush/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appleboy%2Fgorush/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/appleboy","download_url":"https://codeload.github.com/appleboy/gorush/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appleboy%2Fgorush/sbom","scorecard":{"id":203757,"data":{"date":"2025-08-11","repo":{"name":"github.com/appleboy/gorush","commit":"cb1980a31453a250c3ab53651e622537f8a21d35"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.5,"checks":[{"name":"Code-Review","score":1,"reason":"Found 4/30 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":2,"reason":"1 commit(s) and 2 issue activity found in the last 90 days -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql.yaml:27","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yaml:28","Warn: no topLevel permission defined: .github/workflows/codeql.yaml:1","Warn: no topLevel permission defined: .github/workflows/docker.yaml:1","Warn: topLevel 'contents' permission set to 'write': .github/workflows/goreleaser.yml:9","Warn: no topLevel permission defined: .github/workflows/testing.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yaml:40: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/codeql.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yaml:44: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/codeql.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yaml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/codeql.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docker.yaml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/docker.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docker.yaml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/docker.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docker.yaml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/docker.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docker.yaml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/docker.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docker.yaml:40: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/docker.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docker.yaml:46: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/docker.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docker.yaml:54: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/docker.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docker.yaml:66: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/docker.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/goreleaser.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/goreleaser.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/goreleaser.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/goreleaser.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/goreleaser.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/goreleaser.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/testing.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/testing.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/testing.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/testing.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/testing.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/testing.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/testing.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/testing.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/testing.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/testing.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/testing.yml:51: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/testing.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/testing.yml:63: update your workflow using https://app.stepsecurity.io/secureworkflow/appleboy/gorush/testing.yml/master?enable=pin","Warn: containerImage not pinned by hash: docker/Dockerfile:1: pin your Docker image by updating alpine:3.21 to alpine:3.21@sha256:b6a6be0ff92ab6db8acd94f5d1b7a6c2f0f5d10ce3c24af348d333ac6da80685","Info:   0 out of  11 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of  10 third-party GitHubAction dependencies pinned","Info:   0 out of   1 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v1.18.9 not signed: https://api.github.com/repos/appleboy/gorush/releases/193161724","Warn: release artifact v1.18.8 not signed: https://api.github.com/repos/appleboy/gorush/releases/175921691","Warn: release artifact v1.18.7 not signed: https://api.github.com/repos/appleboy/gorush/releases/167381210","Warn: release artifact v1.18.6 not signed: https://api.github.com/repos/appleboy/gorush/releases/165842757","Warn: release artifact v1.18.5 not signed: https://api.github.com/repos/appleboy/gorush/releases/165645029","Warn: release artifact v1.18.9 does not have provenance: https://api.github.com/repos/appleboy/gorush/releases/193161724","Warn: release artifact v1.18.8 does not have provenance: https://api.github.com/repos/appleboy/gorush/releases/175921691","Warn: release artifact v1.18.7 does not have provenance: https://api.github.com/repos/appleboy/gorush/releases/167381210","Warn: release artifact v1.18.6 does not have provenance: https://api.github.com/repos/appleboy/gorush/releases/165842757","Warn: release artifact v1.18.5 does not have provenance: https://api.github.com/repos/appleboy/gorush/releases/165645029"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/docker.yaml:14"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":10,"reason":"SAST tool detected","details":["Info: SAST configuration detected: CodeQL","Info: SAST configuration detected: Hadolint","Warn: 8 commits out of 9 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2025-3488 / GHSA-6v2p-p543-phr9","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-16T23:16:37.938Z","repository_id":37821004,"created_at":"2025-08-16T23:16:37.938Z","updated_at":"2025-08-16T23:16:37.938Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30246874,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T05:41:50.788Z","status":"ssl_error","status_checked_at":"2026-03-08T05:41:39.075Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","apns","gcm","golang","gorush-server","ios","ios-alert-payload","ios-notification","notification-server"],"created_at":"2024-07-30T17:00:59.585Z","updated_at":"2026-03-08T06:03:15.166Z","avatar_url":"https://github.com/appleboy.png","language":"Go","readme":"# gorush\n\nA push notification micro server using [Gin](https://github.com/gin-gonic/gin) framework written in Go (Golang) and see the [demo app](https://github.com/appleboy/flutter-gorush).\n\n[![Run Lint and Testing](https://github.com/appleboy/gorush/actions/workflows/testing.yml/badge.svg)](https://github.com/appleboy/gorush/actions/workflows/testing.yml)\n[![Trivy Security Scan](https://github.com/appleboy/gorush/actions/workflows/trivy-scan.yml/badge.svg)](https://github.com/appleboy/gorush/actions/workflows/trivy-daily-scan.yml)\n[![GoDoc](https://godoc.org/github.com/appleboy/gorush?status.svg)](https://pkg.go.dev/github.com/appleboy/gorush)\n[![codecov](https://codecov.io/gh/appleboy/gorush/branch/master/graph/badge.svg)](https://codecov.io/gh/appleboy/gorush)\n[![Go Report Card](https://goreportcard.com/badge/github.com/appleboy/gorush)](https://goreportcard.com/report/github.com/appleboy/gorush)\n[![Docker Pulls](https://img.shields.io/docker/pulls/appleboy/gorush.svg)](https://hub.docker.com/r/appleboy/gorush/)\n[![Netlify Status](https://api.netlify.com/api/v1/badges/8ab14c9f-44fd-4d9a-8bba-f73f76d253b1/deploy-status)](https://app.netlify.com/sites/gorush/deploys)\n[![Financial Contributors on Open Collective](https://opencollective.com/gorush/all/badge.svg?label=financial+contributors)](https://opencollective.com/gorush)\n\n## Quick Start\n\nGet started with gorush in 3 simple steps:\n\n```bash\n# 1. Download the latest binary\nwget https://github.com/appleboy/gorush/releases/download/v1.18.9/gorush-1.18.9-linux-amd64 -O gorush\nchmod +x gorush\n\n# 2. Start the server (default port 8088)\n./gorush\n\n# 3. Send your first notification\ncurl -X POST http://localhost:8088/api/push \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"notifications\": [{\n      \"tokens\": [\"your_device_token\"],\n      \"platform\": 2,\n      \"title\": \"Hello World\",\n      \"message\": \"Your first notification!\"\n    }]\n  }'\n```\n\n## Contents\n\n- [Quick Start](#quick-start) - Get up and running in 3 steps\n- [Support Platform](#support-platform) - iOS, Android, Huawei\n- [Features](#features) - What gorush can do\n- [Configuration](#configuration) - YAML config and options\n  - [Basic Configuration](#basic-configuration)\n  - [Advanced Configuration](#advanced-configuration)\n- [Installation](#installation) - Binary, package managers, Docker, source\n  - [Recommended: Install Script](#recommended-install-script)\n  - [Manual Download](#manual-download)\n  - [Package Managers](#package-managers)\n  - [Build from Source](#build-from-source)\n  - [Docker](#docker)\n- [Usage](#usage) - CLI commands and REST API examples\n  - [Starting the Server](#starting-the-server)\n  - [Command Line Notifications](#command-line-notifications)\n  - [REST API Usage](#rest-api-usage)\n  - [CLI Options Reference](#cli-options-reference)\n- [Web API](#web-api) - Complete API reference\n  - [Overview](#overview)\n  - [Send Notifications](#send-notifications---post-apipush)\n  - [Statistics APIs](#statistics-apis)\n  - [Request Parameters](#request-parameters)\n- [Deployment](#deployment) - Docker, Kubernetes, AWS Lambda, gRPC\n  - [Docker Deployment](#docker-deployment)\n  - [Kubernetes](#kubernetes)\n  - [AWS Lambda](#aws-lambda)\n  - [Netlify Functions](#netlify-functions)\n  - [gRPC Service](#grpc-service)\n- [FAQ](#faq) - Common issues and best practices\n  - [Common Issues](#common-issues)\n  - [Performance Tips](#performance-tips)\n  - [Security Best Practices](#security-best-practices)\n- [Stargazers over time](#stargazers-over-time)\n- [License](#license)\n\n## Support Platform\n\n📱 Platform codes: `1` = iOS (APNS), `2` = Android (FCM), `3` = Huawei (HMS)\n\n- [APNS](https://developer.apple.com/documentation/usernotifications)\n- [FCM](https://firebase.google.com/)\n- [HMS](https://developer.huawei.com/consumer/en/hms/)\n\n[A live server on Netlify](https://gorush.netlify.app/) and get notification token on [Firebase Cloud Messaging web](https://fcm-demo-88b40.web.app/). You can use the token to send a notification to the device.\n\n```bash\ncurl -X POST \\\n     -H \"Content-Type: application/json\" \\\n     -d '{\n  \"notifications\": [\n    {\n      \"tokens\": [\n        \"your_device_token\"\n      ],\n      \"platform\": 2,\n      \"title\": \"Test Title\",\n      \"message\": \"Test Message\"\n    }\n  ]\n}' \\\n  https://gorush.netlify.app/api/push\n```\n\n## Features\n\n- Support [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging) using [go-fcm](https://github.com/appleboy/go-fcm) library for Android.\n- Support [HTTP/2](https://http2.github.io/) Apple Push Notification Service using [apns2](https://github.com/sideshow/apns2) library.\n- Support [HMS Push Service](https://developer.huawei.com/consumer/en/hms/huawei-pushkit) using [go-hms-push](https://github.com/msalihkarakasli/go-hms-push) library for Huawei Devices.\n- Support [YAML](https://github.com/go-yaml/yaml) configuration.\n- Support command line to send single Android or iOS notification.\n- Support Web API to send push notification.\n- Support [HTTP/2](https://http2.github.io/) or HTTP/1.1 protocol.\n- Support notification queue and multiple workers.\n- Support `/api/stat/app` show notification success and failure counts.\n- Support `/api/config` show your [YAML](https://en.wikipedia.org/wiki/YAML) config.\n- Support store app stat to memory, [Redis](http://redis.io/), [BoltDB](https://github.com/boltdb/bolt), [BuntDB](https://github.com/tidwall/buntdb), [LevelDB](https://github.com/syndtr/goleveldb) or [BadgerDB](https://github.com/dgraph-io/badger).\n- Support `p8`, `p12` or `pem` format of iOS certificate file.\n- Support `/sys/stats` show response time, status code count, etc.\n- Support for HTTP, HTTPS or SOCKS5 proxy.\n- Support retry send notification if server response is fail.\n- Support expose [prometheus](https://prometheus.io/) metrics.\n- Support install TLS certificates from [Let's Encrypt](https://letsencrypt.org/) automatically.\n- Support send notification through [RPC](https://en.wikipedia.org/wiki/Remote_procedure_call) protocol, we use [gRPC](https://grpc.io/) as default framework.\n- Support running in Docker, [Kubernetes](https://kubernetes.io/) or [AWS Lambda](https://aws.amazon.com/lambda) ([Native Support in Golang](https://aws.amazon.com/blogs/compute/announcing-go-support-for-aws-lambda/))\n- Support graceful shutdown that workers and queue have been sent to APNs/FCM before shutdown service.\n- Support different Queue as backend like [NSQ](https://nsq.io/), [NATS](https://nats.io/) or [Redis streams](https://redis.io/docs/manual/data-types/streams/), defaut engine is local [Channel](https://tour.golang.org/concurrency/2).\n\n**Performance**: Average memory usage ~28MB. Supports high-throughput notification delivery with configurable workers and queue systems.\n\n## Configuration\n\nGorush uses YAML configuration. Create a `config.yml` file with your settings:\n\n### Basic Configuration\n\n```yaml\ncore:\n  port: \"8088\" # HTTP server port\n  worker_num: 0 # Workers (0 = CPU cores)\n  queue_num: 8192 # Queue size\n  mode: \"release\" # or \"debug\"\n\n# Enable platforms you need\nandroid:\n  enabled: true\n  key_path: \"fcm-key.json\" # FCM service account key\n\nios:\n  enabled: true\n  key_path: \"apns-key.pem\" # APNS certificate\n  production: true # Use production APNS\n\nhuawei:\n  enabled: false\n  appid: \"YOUR_APP_ID\"\n  appsecret: \"YOUR_APP_SECRET\"\n```\n\n### Advanced Configuration\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand full configuration options\u003c/summary\u003e\n\n```yaml\ncore:\n  enabled: true\n  address: \"\"\n  shutdown_timeout: 30\n  port: \"8088\"\n  worker_num: 0\n  queue_num: 0\n  max_notification: 100\n  sync: false\n  feedback_hook_url: \"\"\n  feedback_timeout: 10\n  feedback_header:\n  mode: \"release\"\n  ssl: false\n  cert_path: \"cert.pem\"\n  key_path: \"key.pem\"\n  cert_base64: \"\"\n  key_base64: \"\"\n  http_proxy: \"\"\n  pid:\n    enabled: false\n    path: \"gorush.pid\"\n    override: true\n  auto_tls:\n    enabled: false\n    folder: \".cache\"\n    host: \"\"\n\ngrpc:\n  enabled: false\n  port: 9000\n\napi:\n  push_uri: \"/api/push\"\n  stat_go_uri: \"/api/stat/go\"\n  stat_app_uri: \"/api/stat/app\"\n  config_uri: \"/api/config\"\n  sys_stat_uri: \"/sys/stats\"\n  metric_uri: \"/metrics\"\n  health_uri: \"/healthz\"\n\nandroid:\n  enabled: true\n  key_path: \"\"\n  credential: \"\"\n  max_retry: 0\n\nhuawei:\n  enabled: false\n  appsecret: \"YOUR_APP_SECRET\"\n  appid: \"YOUR_APP_ID\"\n  max_retry: 0\n\nqueue:\n  engine: \"local\"\n  nsq:\n    addr: 127.0.0.1:4150\n    topic: gorush\n    channel: gorush\n  nats:\n    addr: 127.0.0.1:4222\n    subj: gorush\n    queue: gorush\n  redis:\n    addr: 127.0.0.1:6379\n    group: gorush\n    consumer: gorush\n    stream_name: gorush\n    with_tls: false\n    username: \"\"\n    password: \"\"\n    db: 0\n\nios:\n  enabled: false\n  key_path: \"\"\n  key_base64: \"\"\n  key_type: \"pem\"\n  password: \"\"\n  production: false\n  max_concurrent_pushes: 100\n  max_retry: 0\n  key_id: \"\"\n  team_id: \"\"\n\nlog:\n  format: \"string\"\n  access_log: \"stdout\"\n  access_level: \"debug\"\n  error_log: \"stderr\"\n  error_level: \"error\"\n  hide_token: true\n  hide_messages: false\n\nstat:\n  engine: \"memory\"\n  redis:\n    cluster: false\n    addr: \"localhost:6379\"\n    username: \"\"\n    password: \"\"\n    db: 0\n  boltdb:\n    path: \"bolt.db\"\n    bucket: \"gorush\"\n  buntdb:\n    path: \"bunt.db\"\n  leveldb:\n    path: \"level.db\"\n  badgerdb:\n    path: \"badger.db\"\n```\n\nSee the complete [example config file](config/testdata/config.yml).\n\n\u003c/details\u003e\n\n## Installation\n\n### Recommended: Install Script\n\nThe easiest way to install gorush is using the install script:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/appleboy/gorush/master/install.sh | bash\n```\n\nThis will automatically:\n\n- Detect your OS and architecture\n- Download the latest version\n- Install to `~/.gorush/bin`\n- Add to your PATH\n\n#### Options\n\n```bash\n# Install specific version (replace X.Y.Z with the desired version, e.g., 1.19.2)\nVERSION=X.Y.Z curl -fsSL https://raw.githubusercontent.com/appleboy/gorush/master/install.sh | bash\n\n# Custom install directory\nINSTALL_DIR=/usr/local/bin curl -fsSL https://raw.githubusercontent.com/appleboy/gorush/master/install.sh | bash\n\n# Skip SSL verification (not recommended)\nINSECURE=1 curl -fsSL https://raw.githubusercontent.com/appleboy/gorush/master/install.sh | bash\n```\n\n### Manual Download\n\nDownload from [releases page](https://github.com/appleboy/gorush/releases):\n\n### Package Managers\n\n#### Homebrew (macOS/Linux)\n\n```bash\nbrew tap appleboy/tap\nbrew install gorush\n```\n\n#### Go Install\n\n```bash\n# Latest stable version\ngo install github.com/appleboy/gorush@latest\n\n# Development version\ngo install github.com/appleboy/gorush@master\n```\n\n### Build from Source\n\n**Requirements**: [Go 1.24+](https://go.dev/dl/), [Git](http://git-scm.com/)\n\n```bash\ngit clone https://github.com/appleboy/gorush.git\ncd gorush\nmake build\n# Binary will be in the root directory\n```\n\n### Docker\n\n```bash\n# Run directly\ndocker run --rm -p 8088:8088 appleboy/gorush\n\n# With custom config\ndocker run --rm -p 8088:8088 -v $(pwd)/config.yml:/home/gorush/config.yml appleboy/gorush\n```\n\n## Usage\n\n### Starting the Server\n\n```bash\n# Use default config (port 8088)\n./gorush\n\n# Use custom config file\n./gorush -c config.yml\n\n# Set specific options\n./gorush -p 9000 -c config.yml\n```\n\n### Command Line Notifications\n\n#### Android (FCM) Command Line\n\n**Prerequisites**: Generate FCM service account key from [Firebase Console](https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk) → Settings → Service Accounts → Generate New Private Key.\n\n```bash\n# Android: Single notification\ngorush -android -m \"Hello Android!\" --fcm-key \"path/to/fcm-key.json\" -t \"device_token\"\n\n# Android: Using environment variable (recommended)\nexport GOOGLE_APPLICATION_CREDENTIALS=\"path/to/fcm-key.json\"\ngorush -android -m \"Hello Android!\" -t \"device_token\"\n\n# Android: Topic message\ngorush --android --topic \"news\" -m \"Breaking News!\" --fcm-key \"path/to/fcm-key.json\"\n```\n\n#### iOS (APNS) Command Line\n\n```bash\n# iOS: Development environment\ngorush -ios -m \"Hello iOS!\" -i \"cert.pem\" -t \"device_token\" --topic \"com.example.app\"\n\n# iOS: Production environment\ngorush -ios -m \"Hello iOS!\" -i \"cert.pem\" -t \"device_token\" --topic \"com.example.app\" -production\n\n# iOS: With password-protected certificate\ngorush -ios -m \"Hello iOS!\" -i \"cert.p12\" -P \"cert_password\" -t \"device_token\"\n```\n\n#### Huawei (HMS) Command Line\n\n```bash\n# Huawei: Single notification\ngorush -huawei -title \"Hello\" -m \"Hello Huawei!\" -hk \"APP_SECRET\" -hid \"APP_ID\" -t \"device_token\"\n\n# Huawei: Topic message\ngorush --huawei --topic \"updates\" -title \"Update\" -m \"New version available\" -hk \"APP_SECRET\" -hid \"APP_ID\"\n```\n\n### REST API Usage\n\n#### Health Check\n\n```bash\ncurl http://localhost:8088/healthz\n```\n\n#### Send Notifications\n\n```bash\ncurl -X POST http://localhost:8088/api/push \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"notifications\": [{\n      \"tokens\": [\"device_token_1\", \"device_token_2\"],\n      \"platform\": 2,\n      \"title\": \"Hello World\",\n      \"message\": \"This is a test notification\"\n    }]\n  }'\n```\n\n#### Get Statistics\n\n```bash\n# Application stats\ncurl http://localhost:8088/api/stat/app\n\n# Go runtime stats\ncurl http://localhost:8088/api/stat/go\n\n# System stats\ncurl http://localhost:8088/sys/stats\n\n# Prometheus metrics\ncurl http://localhost:8088/metrics\n```\n\n### CLI Options Reference\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand all CLI options\u003c/summary\u003e\n\n```bash\nServer Options:\n    -A, --address \u003caddress\u003e          Address to bind (default: any)\n    -p, --port \u003cport\u003e                Use port for clients (default: 8088)\n    -c, --config \u003cfile\u003e              Configuration file path\n    -m, --message \u003cmessage\u003e          Notification message\n    -t, --token \u003ctoken\u003e              Notification token\n    -e, --engine \u003cengine\u003e            Storage engine (memory, redis ...)\n    --title \u003ctitle\u003e                  Notification title\n    --proxy \u003cproxy\u003e                  Proxy URL\n    --pid \u003cpid path\u003e                 Process identifier path\n    --redis-addr \u003credis addr\u003e        Redis addr (default: localhost:6379)\n    --ping                           healthy check command for container\n\niOS Options:\n    -i, --key \u003cfile\u003e                 certificate key file path\n    -P, --password \u003cpassword\u003e        certificate key password\n    --ios                            enabled iOS (default: false)\n    --production                     iOS production mode (default: false)\n\nAndroid Options:\n    --fcm-key \u003cfcm_key_path\u003e         FCM Key Path\n    --android                        enabled android (default: false)\n\nHuawei Options:\n    -hk, --hmskey \u003chms_key\u003e          HMS App Secret\n    -hid, --hmsid \u003chms_id\u003e           HMS App ID\n    --huawei                         enabled huawei (default: false)\n\nCommon Options:\n    --topic \u003ctopic\u003e                  iOS, Android or Huawei topic message\n    -h, --help                       Show this message\n    -V, --version                    Show version\n```\n\n\u003c/details\u003e\n\n## Web API\n\n### Overview\n\nGorush provides RESTful APIs for sending notifications and monitoring system status:\n\n| Endpoint        | Method | Description                |\n| --------------- | ------ | -------------------------- |\n| `/api/push`     | POST   | Send push notifications    |\n| `/api/stat/app` | GET    | Application statistics     |\n| `/api/stat/go`  | GET    | Go runtime statistics      |\n| `/sys/stats`    | GET    | System performance metrics |\n| `/metrics`      | GET    | Prometheus metrics         |\n| `/healthz`      | GET    | Health check               |\n| `/api/config`   | GET    | Current configuration      |\n\n### Send Notifications - `POST /api/push`\n\n#### Basic Examples\n\n##### iOS (APNS) API\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"ios_device_token\"],\n      \"platform\": 1,\n      \"title\": \"Hello iOS\",\n      \"message\": \"Hello World iOS!\"\n    }\n  ]\n}\n```\n\n##### Android (FCM) API\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"android_device_token\"],\n      \"platform\": 2,\n      \"title\": \"Hello Android\",\n      \"message\": \"Hello World Android!\"\n    }\n  ]\n}\n```\n\n##### Huawei (HMS) API\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"huawei_device_token\"],\n      \"platform\": 3,\n      \"title\": \"Hello Huawei\",\n      \"message\": \"Hello World Huawei!\"\n    }\n  ]\n}\n```\n\n#### Advanced Examples\n\n##### iOS with Custom Sound\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"ios_device_token\"],\n      \"platform\": 1,\n      \"title\": \"Important Alert\",\n      \"message\": \"Critical notification\",\n      \"apns\": {\n        \"payload\": {\n          \"aps\": {\n            \"sound\": {\n              \"name\": \"custom.wav\",\n              \"critical\": 1,\n              \"volume\": 0.8\n            }\n          }\n        }\n      }\n    }\n  ]\n}\n```\n\n##### Multiple Platforms\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"ios_token\"],\n      \"platform\": 1,\n      \"message\": \"Hello iOS!\"\n    },\n    {\n      \"tokens\": [\"android_token\"],\n      \"platform\": 2,\n      \"message\": \"Hello Android!\"\n    }\n  ]\n}\n```\n\n### Statistics APIs\n\n#### Application Stats - `GET /api/stat/app`\n\n```json\n{\n  \"version\": \"v1.18.9\",\n  \"busy_workers\": 0,\n  \"success_tasks\": 150,\n  \"failure_tasks\": 5,\n  \"submitted_tasks\": 155,\n  \"total_count\": 155,\n  \"ios\": {\n    \"push_success\": 80,\n    \"push_error\": 2\n  },\n  \"android\": {\n    \"push_success\": 65,\n    \"push_error\": 3\n  },\n  \"huawei\": {\n    \"push_success\": 5,\n    \"push_error\": 0\n  }\n}\n```\n\n#### System Performance - `GET /sys/stats`\n\n```json\n{\n  \"pid\": 12345,\n  \"uptime\": \"2h30m15s\",\n  \"total_response_time\": \"45.2ms\",\n  \"average_response_time\": \"1.2ms\",\n  \"total_status_code_count\": {\n    \"200\": 1450,\n    \"400\": 12,\n    \"500\": 3\n  }\n}\n```\n\n### Request Parameters\n\n\u003cdetails\u003e\n\u003csummary\u003eComplete API request parameters\u003c/summary\u003e\n\n#### Request body\n\nThe Request body must have a notifications array. The following is a parameter table for each notification.\n\n| name                    | type         | description                                                                                       | required | note                                                          |\n| ----------------------- | ------------ | ------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------- |\n| notif_id                | string       | A unique string that identifies the notification for async feedback                               | -        |                                                               |\n| tokens                  | string array | device tokens                                                                                     | o        |                                                               |\n| platform                | int          | platform(iOS,Android)                                                                             | o        | 1=iOS, 2=Android (Firebase), 3=Huawei (HMS)                   |\n| message                 | string       | message for notification                                                                          | -        |                                                               |\n| title                   | string       | notification title                                                                                | -        |                                                               |\n| priority                | string       | Sets the priority of the message.                                                                 | -        | `normal` or `high`                                            |\n| content_available       | bool         | data messages wake the app by default.                                                            | -        |                                                               |\n| sound                   | interface{}  | sound type                                                                                        | -        |                                                               |\n| data                    | string array | extensible partition                                                                              | -        | only Android and IOS                                          |\n| huawei_data             | string       | JSON object as string to extensible partition partition                                           | -        | only Huawei. See the [detail](#huawei-notification)           |\n| retry                   | int          | retry send notification if fail response from server. Value must be small than `max_retry` field. | -        |                                                               |\n| topic                   | string       | send messages to topics                                                                           |          |                                                               |\n| image                   | string       | image url to show in notification                                                                 | -        | only Android and Huawei                                       |\n| to                      | string       | The value must be a registration token, notification key, or topic.                               | -        | only Android                                                  |\n| collapse_key            | string       | a key for collapsing notifications                                                                | -        | only Android                                                  |\n| huawei_collapse_key     | int          | a key integer for collapsing notifications                                                        | -        | only Huawei See the [detail](#huawei-notification)            |\n| delay_while_idle        | bool         | a flag for device idling                                                                          | -        | only Android                                                  |\n| time_to_live            | uint         | expiration of message kept on FCM storage                                                         | -        | only Android                                                  |\n| huawei_ttl              | string       | expiration of message kept on HMS storage                                                         | -        | only Huawei See the [detail](#huawei-notification)            |\n| restricted_package_name | string       | the package name of the application                                                               | -        | only Android                                                  |\n| dry_run                 | bool         | allows developers to test a request without actually sending a message                            | -        | only Android                                                  |\n| notification            | string array | payload of a FCM message                                                                          | -        | only Android. See the [detail](#android-notification-payload) |\n| huawei_notification     | string array | payload of a HMS message                                                                          | -        | only Huawei. See the [detail](#huawei-notification)           |\n| app_id                  | string       | hms app id                                                                                        | -        | only Huawei. See the [detail](#huawei-notification)           |\n| bi_tag                  | string       | Tag of a message in a batch delivery task                                                         | -        | only Huawei. See the [detail](#huawei-notification)           |\n| fast_app_target         | int          | State of a mini program when a quick app sends a data message.                                    | -        | only Huawei. See the [detail](#huawei-notification)           |\n| expiration              | int          | expiration for notification                                                                       | -        | only iOS                                                      |\n| apns_id                 | string       | A canonical UUID that identifies the notification                                                 | -        | only iOS                                                      |\n| collapse_id             | string       | An identifier you use to coalesce multiple notifications into a single notification for the user  | -        | only iOS                                                      |\n| push_type               | string       | The type of the notification. The value of this header is alert or background.                    | -        | only iOS                                                      |\n| badge                   | int          | badge count                                                                                       | -        | only iOS                                                      |\n| category                | string       | the UIMutableUserNotificationCategory object                                                      | -        | only iOS                                                      |\n| alert                   | string array | payload of a iOS message                                                                          | -        | only iOS. See the [detail](#ios-alert-payload)                |\n| mutable_content         | bool         | enable Notification Service app extension.                                                        | -        | only iOS(10.0+).                                              |\n| name                    | string       | sets the name value on the aps sound dictionary.                                                  | -        | only iOS                                                      |\n| volume                  | float32      | sets the volume value on the aps sound dictionary.                                                | -        | only iOS                                                      |\n| interruption_level      | string       | defines the interruption level for the push notification.                                         | -        | only iOS(15.0+)                                               |\n| content-state           | string array | dynamic and custom content for live-activity notification.                                        | -        | only iOS(16.1+)                                               |\n| timestamp               | int          | the UNIX time when sending the remote notification that updates or ends a Live Activity           | -        | only iOS(16.1+)                                               |\n| event                   | string       | describes whether you update or end an ongoing Live Activity                                      | -        | only iOS(16.1+)                                               |\n| stale-date              | int          | the date which a Live Activity becomes stale, or out of date                                      | -        | only iOS(16.1+)                                               |\n| dismissal-date          | int          | the UNIX time -timestamp- which a Live Activity will end and will be removed                      | -        | only iOS(16.1+)                                               |\n\n### iOS alert payload\n\n| name           | type             | description                                                                                      | required | note |\n| -------------- | ---------------- | ------------------------------------------------------------------------------------------------ | -------- | ---- |\n| title          | string           | Apple Watch \u0026 Safari display this string as part of the notification interface.                  | -        |      |\n| body           | string           | The text of the alert message.                                                                   | -        |      |\n| subtitle       | string           | Apple Watch \u0026 Safari display this string as part of the notification interface.                  | -        |      |\n| action         | string           | The label of the action button. This one is required for Safari Push Notifications.              | -        |      |\n| action-loc-key | string           | If a string is specified, the system displays an alert that includes the Close and View buttons. | -        |      |\n| launch-image   | string           | The filename of an image file in the app bundle, with or without the filename extension.         | -        |      |\n| loc-args       | array of strings | Variable string values to appear in place of the format specifiers in loc-key.                   | -        |      |\n| loc-key        | string           | A key to an alert-message string in a Localizable.strings file for the current localization.     | -        |      |\n| title-loc-args | array of strings | Variable string values to appear in place of the format specifiers in title-loc-key.             | -        |      |\n| title-loc-key  | string           | The key to a title string in the Localizable.strings file for the current localization.          | -        |      |\n\nSee more detail about [APNs Remote Notification Payload](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html).\n\n### iOS sound payload\n\n| name     | type    | description                                          | required | note |\n| -------- | ------- | ---------------------------------------------------- | -------- | ---- |\n| name     | string  | sets the name value on the aps sound dictionary.     | -        |      |\n| volume   | float32 | sets the volume value on the aps sound dictionary.   | -        |      |\n| critical | int     | sets the critical value on the aps sound dictionary. | -        |      |\n\nrequest format:\n\n```json\n{\n  \"sound\": {\n    \"critical\": 1,\n    \"name\": \"default\",\n    \"volume\": 2.0\n  }\n}\n```\n\n### Android notification payload\n\n| name           | type   | description                                                                                               | required | note |\n| -------------- | ------ | --------------------------------------------------------------------------------------------------------- | -------- | ---- |\n| icon           | string | Indicates notification icon.                                                                              | -        |      |\n| tag            | string | Indicates whether each notification message results in a new entry on the notification center on Android. | -        |      |\n| color          | string | Indicates color of the icon, expressed in #rrggbb format                                                  | -        |      |\n| click_action   | string | The action associated with a user click on the notification.                                              | -        |      |\n| body_loc_key   | string | Indicates the key to the body string for localization.                                                    | -        |      |\n| body_loc_args  | string | Indicates the string value to replace format specifiers in body string for localization.                  | -        |      |\n| title_loc_key  | string | Indicates the key to the title string for localization.                                                   | -        |      |\n| title_loc_args | string | Indicates the string value to replace format specifiers in title string for localization.                 | -        |      |\n\nSee more detail about [Firebase Cloud Messaging HTTP Protocol reference](https://firebase.google.com/docs/cloud-messaging/http-server-ref#send-downstream).\n\n### Huawei notification\n\n1. app_id: app id from huawei developer console\n2. bi_tag:\n3. fast_app_target:\n4. huawei_data: mapped to data\n5. huawei_notification: mapped to notification\n6. huawei_ttl: mapped to ttl\n7. huawei_collapse_key: mapped to collapse_key\n\nSee more detail about [Huawei Mobulse Services Push API reference](https://developer.huawei.com/consumer/en/doc/development/HMS-References/push-sendapi).\n\n### iOS Example\n\nSend normal notification.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 1,\n      \"message\": \"Hello World iOS!\"\n    }\n  ]\n}\n```\n\nThe following payload asks the system to display an alert with a Close button and a single action button.The title and body keys provide the contents of the alert. The “PLAY” string is used to retrieve a localized string from the appropriate Localizable.strings file of the app. The resulting string is used by the alert as the title of an action button. This payload also asks the system to badge the app’s icon with the number 5.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 1,\n      \"badge\": 5,\n      \"alert\": {\n        \"title\": \"Game Request\",\n        \"body\": \"Bob wants to play poker\",\n        \"action-loc-key\": \"PLAY\"\n      }\n    }\n  ]\n}\n```\n\nThe following payload specifies that the device should display an alert message, plays a sound, and badges the app’s icon.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 1,\n      \"message\": \"You got your emails.\",\n      \"badge\": 9,\n      \"sound\": {\n        \"critical\": 1,\n        \"name\": \"default\",\n        \"volume\": 1.0\n      }\n    }\n  ]\n}\n```\n\nAdd other fields which user defined via `data` field.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 1,\n      \"message\": \"Hello World iOS!\",\n      \"data\": {\n        \"key1\": \"welcome\",\n        \"key2\": 2\n      }\n    }\n  ]\n}\n```\n\nSupport send notification from different environment. See the detail of [issue](https://github.com/appleboy/gorush/issues/246).\n\n```diff\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 1,\n+     \"production\": true,\n      \"message\": \"Hello World iOS Production!\"\n    },\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 1,\n+     \"development\": true,\n      \"message\": \"Hello World iOS Sandbox!\"\n    }\n  ]\n}\n```\n\n### Android Example\n\nSend normal notification.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 2,\n      \"message\": \"Hello World Android!\",\n      \"title\": \"You got message\"\n    }\n  ]\n}\n```\n\nLabel associated with the message's analytics data.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 2,\n      \"message\": \"Hello World Android!\",\n      \"title\": \"You got message\",\n      \"fcm_options\": {\n        \"analytics_label\": \"example\"\n      }\n    }\n  ]\n}\n```\n\nAdd `notification` payload.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 2,\n      \"message\": \"Hello World Android!\",\n      \"title\": \"You got message\",\n      \"notification\": {\n        \"icon\": \"myicon\",\n        \"color\": \"#112244\"\n      }\n    }\n  ]\n}\n```\n\nAdd other fields which user defined via `data` field.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 2,\n      \"message\": \"Hello World Android!\",\n      \"title\": \"You got message\",\n      \"data\": {\n        \"Nick\": \"Mario\",\n        \"body\": \"great match!\",\n        \"Room\": \"PortugalVSDenmark\"\n      }\n    }\n  ]\n}\n```\n\nSend messages to topic\n\n```json\n{\n  \"notifications\": [\n    {\n      \"topic\": \"highScores\",\n      \"platform\": 2,\n      \"message\": \"This is a Firebase Cloud Messaging Topic Message\"\n    }\n  ]\n}\n```\n\n### Huawei Example\n\nSend normal notification.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 3,\n      \"message\": \"Hello World Huawei!\",\n      \"title\": \"You got message\"\n    }\n  ]\n}\n```\n\nAdd `notification` payload.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 3,\n      \"message\": \"Hello World Huawei!\",\n      \"title\": \"You got message\",\n      \"huawei_notification\": {\n        \"icon\": \"myicon\",\n        \"color\": \"#112244\"\n      }\n    }\n  ]\n}\n```\n\nAdd other fields which user defined via `huawei_data` field.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 3,\n      \"huawei_data\": \"{'title' : 'Mario','message' : 'great match!', 'Room' : 'PortugalVSDenmark'}\"\n    }\n  ]\n}\n```\n\nSend messages to topics\n\n```json\n{\n  \"notifications\": [\n    {\n      \"topic\": \"foo-bar\",\n      \"platform\": 3,\n      \"message\": \"This is a Huawei Mobile Services Topic Message\",\n      \"title\": \"You got message\"\n    }\n  ]\n}\n```\n\n### Response body\n\nError response message table:\n\n| status code | message                                    |\n| ----------- | ------------------------------------------ |\n| 400         | Missing `notifications` field.             |\n| 400         | Notifications field is empty.              |\n| 400         | Number of notifications(50) over limit(10) |\n\nSuccess response:\n\n```json\n{\n  \"counts\": 60,\n  \"logs\": [],\n  \"success\": \"ok\"\n}\n```\n\nIf you need error logs from sending fail notifications, please set a `feedback_hook_url` and `feedback_header` for custom header. The server with send the failing logs asynchronously to your API as `POST` requests.\n\n```diff\ncore:\n  port: \"8088\" # ignore this port number if auto_tls is enabled (listen 443).\n  worker_num: 0 # default worker number is runtime.NumCPU()\n  queue_num: 0 # default queue number is 8192\n  max_notification: 100\n  sync: false\n- feedback_hook_url: \"\"\n+ feedback_hook_url: \"https://exemple.com/api/hook\"\n+ feedback_header:\n+   - x-gorush-token:4e989115e09680f44a645519fed6a976\n```\n\nYou can also switch to **sync** mode by setting the `sync` value as `true` on yaml config. It only works when the queue engine is local.\n\n```diff\ncore:\n  port: \"8088\" # ignore this port number if auto_tls is enabled (listen 443).\n  worker_num: 0 # default worker number is runtime.NumCPU()\n  queue_num: 0 # default queue number is 8192\n  max_notification: 100\n- sync: false\n+ sync: true\n```\n\nSee the following error format.\n\n```json\n{\n  \"counts\": 60,\n  \"logs\": [\n    {\n      \"type\": \"failed-push\",\n      \"platform\": \"android\",\n      \"token\": \"*******\",\n      \"message\": \"Hello World Android!\",\n      \"error\": \"InvalidRegistration\"\n    },\n    {\n      \"type\": \"failed-push\",\n      \"platform\": \"ios\",\n      \"token\": \"*****\",\n      \"message\": \"Hello World iOS1111!\",\n      \"error\": \"Post https://api.push.apple.com/3/device/bbbbb: remote error: tls: revoked certificate\"\n    },\n    {\n      \"type\": \"failed-push\",\n      \"platform\": \"ios\",\n      \"token\": \"*******\",\n      \"message\": \"Hello World iOS222!\",\n      \"error\": \"Post https://api.push.apple.com/3/device/token_b: remote error: tls: revoked certificate\"\n    }\n  ],\n  \"success\": \"ok\"\n}\n```\n\n## Deployment\n\n### Docker Deployment\n\n#### Docker Quick Start\n\n```bash\n# Run with default config\ndocker run --rm -p 8088:8088 appleboy/gorush\n\n# Run with custom config\ndocker run --rm -p 8088:8088 \\\n  -v $(pwd)/config.yml:/home/gorush/config.yml \\\n  appleboy/gorush\n\n# Run in background\ndocker run -d --name gorush -p 8088:8088 appleboy/gorush\n```\n\n#### Docker Compose\n\n```yaml\nversion: \"3\"\nservices:\n  gorush:\n    image: appleboy/gorush\n    ports:\n      - \"8088:8088\"\n    volumes:\n      - ./config.yml:/home/gorush/config.yml\n  redis:\n    image: redis:alpine\n    ports:\n      - \"6379:6379\"\n```\n\n### Kubernetes\n\n#### Quick Deploy\n\n```bash\n# Create namespace and config\nkubectl create -f k8s/gorush-namespace.yaml\nkubectl create -f k8s/gorush-configmap.yaml\n\n# Deploy Redis (optional, for queue/stats)\nkubectl create -f k8s/gorush-redis-deployment.yaml\nkubectl create -f k8s/gorush-redis-service.yaml\n\n# Deploy Gorush\nkubectl create -f k8s/gorush-deployment.yaml\nkubectl create -f k8s/gorush-service.yaml\n```\n\n#### AWS Load Balancer\n\nFor AWS ELB:\n\n```bash\nkubectl create -f k8s/gorush-service.yaml\n```\n\nFor AWS ALB, modify service type:\n\n```yaml\n# k8s/gorush-service.yaml\nspec:\n  type: NodePort # Change from LoadBalancer\n```\n\nThen deploy ingress:\n\n```bash\nkubectl create -f k8s/gorush-aws-alb-ingress.yaml\n```\n\n#### Cleanup\n\n```bash\nkubectl delete -f k8s/\n```\n\n### AWS Lambda\n\n#### Build and Deploy\n\n```bash\n# Build Lambda binary\ngit clone https://github.com/appleboy/gorush.git\ncd gorush\nmake build_linux_lambda\n\n# Create deployment package\nzip deployment.zip release/linux/lambda/gorush\n\n# Deploy with AWS CLI\naws lambda update-function-code \\\n  --function-name gorush \\\n  --zip-file fileb://deployment.zip\n```\n\n#### Automated Deployment\n\nUsing [drone-lambda](https://github.com/appleboy/drone-lambda):\n\n```bash\nAWS_ACCESS_KEY_ID=your_key \\\nAWS_SECRET_ACCESS_KEY=your_secret \\\ndrone-lambda --region us-west-2 \\\n  --function-name gorush \\\n  --source release/linux/lambda/gorush\n```\n\n### Netlify Functions\n\nAlternative serverless deployment without AWS:\n\n```toml\n# netlify.toml\n[build]\ncommand = \"make build_linux_lambda\"\nfunctions = \"release/linux/lambda\"\n\n[build.environment]\nGO_VERSION = \"1.24\"\n\n[[redirects]]\nfrom = \"/*\"\nstatus = 200\nto = \"/.netlify/functions/gorush/:splat\"\n```\n\n### gRPC Service\n\nEnable gRPC server for high-performance applications:\n\n```yaml\n# config.yml\ngrpc:\n  enabled: true\n  port: 9000\n```\n\nOr via environment:\n\n```bash\nGORUSH_GRPC_ENABLED=true GORUSH_GRPC_PORT=9000 gorush\n```\n\n#### gRPC Client Example (Go)\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log\"\n    \"github.com/appleboy/gorush/rpc/proto\"\n    \"google.golang.org/grpc\"\n)\n\nfunc main() {\n    conn, err := grpc.NewClient(\"localhost:9000\", grpc.WithInsecure())\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer conn.Close()\n\n    client := proto.NewGorushClient(conn)\n    resp, err := client.Send(context.Background(), \u0026proto.NotificationRequest{\n        Platform: 2,\n        Tokens:   []string{\"device_token\"},\n        Message:  \"Hello gRPC!\",\n        Title:    \"Test Notification\",\n    })\n\n    if err != nil {\n        log.Fatal(err)\n    }\n    log.Printf(\"Success: %v, Count: %d\", resp.Success, resp.Counts)\n}\n```\n\n## FAQ\n\n### Common Issues\n\n#### Q: How do I get FCM credentials?\n\nA: Go to [Firebase Console](https://console.firebase.google.com/) → Project Settings → Service Accounts → Generate New Private Key. Download the JSON file.\n\n#### Q: iOS notifications not working in production?\n\nA: Make sure you:\n\n1. Use production APNS certificates (`production: true`)\n2. Set correct bundle ID in certificate\n3. Test with production app build\n\n#### Q: Getting \"certificate verify failed\" error?\n\nA: This usually means:\n\n- Wrong certificate format (use `.pem` or `.p12`)\n- Certificate expired\n- Wrong environment (dev vs production)\n\n#### Q: How to handle large notification volumes?\n\nA: Configure workers and queue settings:\n\n```yaml\ncore:\n  worker_num: 8 # Increase workers\n  queue_num: 16384 # Increase queue size\nqueue:\n  engine: \"redis\" # Use external queue\n```\n\n#### Q: Can I send to multiple platforms at once?\n\nA: Yes, include multiple notification objects in the request:\n\n```json\n{\n  \"notifications\": [\n    { \"platform\": 1, \"tokens\": [\"ios_token\"], \"message\": \"iOS\" },\n    { \"platform\": 2, \"tokens\": [\"android_token\"], \"message\": \"Android\" }\n  ]\n}\n```\n\n#### Q: How to monitor notification failures?\n\nA: Enable sync mode or feedback webhook:\n\n```yaml\ncore:\n  sync: true # Get immediate response\n  feedback_hook_url: \"https://your-api\" # Async webhook\n```\n\n#### Q: What's the difference between platforms?\n\nA: Platform codes: `1` = iOS (APNS), `2` = Android (FCM), `3` = Huawei (HMS)\n\n### Performance Tips\n\n- Use Redis for queue and stats storage in production\n- Enable gRPC for better performance\n- Set appropriate worker numbers based on CPU cores\n- Use connection pooling for high-volume scenarios\n\n### Security Best Practices\n\n- Store credentials as files, not in config\n- Use environment variables for sensitive data\n- Enable SSL/TLS in production\n- Rotate certificates before expiration\n- Monitor failed notifications for security issues\n\n## Stargazers over time\n\n[![Stargazers over time](https://starchart.cc/appleboy/gorush.svg)](https://starchart.cc/appleboy/gorush)\n\n## License\n\nCopyright 2026 Bo-Yi Wu [@appleboy](https://github.com/appleboy).\n\nLicensed under the MIT License.\n","funding_links":["https://github.com/sponsors/appleboy","https://opencollective.com/gorush","https://www.paypal.me/appleboy46"],"categories":["Go","Popular","开源类库","Messaging","Open source library","Gin project in real world","Relational Databases","消息","Repositories","\u003cspan id=\"消息-messaging\"\u003e消息 Messaging\u003c/span\u003e","网络信息服务","消息系统","消息传递","机器学习"],"sub_categories":["未归类","Search and Analytic Databases","Advanced Console UIs","Not Categorized","检索及分析资料库","\u003cspan id=\"高级控制台用户界面-advanced-console-uis\"\u003e高级控制台用户界面 Advanced Console UIs\u003c/span\u003e","信息沟通","SQL 查询语句构建库","交流"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fappleboy%2Fgorush","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fappleboy%2Fgorush","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fappleboy%2Fgorush/lists"}