Since we reached two important milestones for Go developers working with InterSystems IRIS:
Now it’s time to see everything working together.
To demonstrate how easily Go developers can adopt InterSystems IRIS, I took an existing production-grade open-source project — the RealWorld Example App — which showcases a full-stack Medium.com-style clone implemented with Go Fiber, GORM, and SQLite.

With just a few configuration tweaks, I swapped out SQLite for gorm-iris, keeping everything else unchanged. The result?
A fully functional Go + Fiber application powered by InterSystems IRIS — no code rewrites, no ORM gymnastics, just a different database backend.
You can find the complete working demo here: github.com/caretdev/golang-fiber-iris-realworld-example-app
Getting Started
Let’s run the demo project.
1. Clone the Project
git clone git@github.com:caretdev/golang-fiber-iris-realworld-example-app.git
cd golang-fiber-iris-realworld-example-app
2. Download Dependencies and Generate Swagger Docs
Install Go dependencies and generate the API documentation:
go mod download
go install github.com/swaggo/swag/cmd/swag@latest
go generate .
This will:
- Download all required Go modules.
- Install the
swag
tool for generating Swagger documentation.
- Execute the Go
generate
command, which rebuilds Swagger definitions from annotations in the codebase.
After running this, you should see the generated documentation files under the docs/
directory.
3. Database Setup and Testing
The project includes a db.go
file, which defines the logic for initializing a database connection.
To simplify testing and ensure a clean environment, we’re using testcontainers-iris-go — it spins up a fresh InterSystems IRIS container for each test run.
This means every test starts with an empty, isolated IRIS instance — ideal for reliable automated testing.
Here’s the core part of the code that makes it work:
var container *iriscontainer.IRISContainer
func TestDB(useContainer bool) *gorm.DB {
var err error
var connectionString = "iris://_SYSTEM:SYS@localhost:1972/USER"
if useContainer {
options := []testcontainers.ContainerCustomizer{
iriscontainer.WithNamespace("TEST"),
iriscontainer.WithUsername("testuser"),
iriscontainer.WithPassword("testpassword"),
}
ctx := context.Background()
container, err = iriscontainer.RunContainer(ctx, options...)
if err != nil {
log.Println("Failed to start container:", err)
os.Exit(1)
}
connectionString = container.MustConnectionString(ctx)
fmt.Println("Container started: ", connectionString)
}
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags),
logger.Config{
SlowThreshold: time.Second,
LogLevel: logger.Error,
Colorful: true,
},
)
db, err := gorm.Open(iris.New(iris.Config{
DSN: connectionString,
}), &gorm.Config{
Logger: newLogger,
})
if !useContainer {
_ = db.Exec("DROP DATABASE TEST").Error
_ = db.Exec("CREATE DATABASE TEST").Error
_ = db.Exec("USE DATABASE TEST").Error
}
if err != nil {
fmt.Println("storage err: ", err)
}
return db
}
func DropTestDB() error {
if container != nil {
container.Terminate(context.Background())
}
container = nil
return nil
}
func AutoMigrate(db *gorm.DB) {
db.AutoMigrate(
&model.User{},
&model.Follow{},
&model.Article{},
&model.Comment{},
&model.Tag{},
)
}
Using containerized IRIS is set under a cli flag and set in a handler_test.go file
var (
useContainer bool
)
func TestMain(m *testing.M) {
flag.BoolVar(&useContainer, "container", true, "Use container image.")
flag.Parse()
code := m.Run()
os.Exit(code)
}
func setup() {
d = db.TestDB(useContainer)
db.AutoMigrate(d)
us = store.NewUserStore(d)
as = store.NewArticleStore(d)
h = NewHandler(us, as)
e = router.New()
loadFixtures()
}
How It Works
- When
useContainer
is true
, the function launches a new IRIS container via testcontainers-iris-go
.
- It creates a clean environment with custom credentials (
testuser
/ testpassword
) and a namespace called TEST
.
- The connection string is retrieved automatically via
container.MustConnectionString(ctx)
.
- When running locally without containers, the code connects to a pre-existing IRIS instance and ensures the
TEST
database is recreated before tests run.
AutoMigrate()
automatically creates all required tables using the models defined in the project (User
, Article
, Comment
, etc.).
4. Run the Tests
Once the database configuration is in place, you can execute all tests using:
go test ./handler -v
flag -container or -container=0 can be added to swich the way of testing
This command will:
- Build and run all Go tests in verbose mode.
- Start a new IRIS container for each test (if enabled).
- Automatically apply migrations and clean up after completion.
If everything is configured correctly, you’ll see log output similar to:
=== RUN TestListArticlesCaseSuccess 2025/10/07 23:29:20 /Users/daimor/Projects/golang-fiber-realworld-example-app/store/user.go:105 record not found
[22.836ms] [rows:0] SELECT * FROM "follows" WHERE following_id = 2 AND follower_id = 0 ORDER BY "follows"."follower_id" LIMIT 1 2025/10/07 23:29:20 /Users/daimor/Projects/golang-fiber-realworld-example-app/store/user.go:105 record not found
[0.491ms] [rows:0] SELECT * FROM "follows" WHERE following_id = 1 AND follower_id = 0 ORDER BY "follows"."follower_id" LIMIT 1
23:29:20 | 200 | 112.944458ms | 0.0.0.0 | GET | /api/articles | -
--- PASS: TestListArticlesCaseSuccess (3.95s)
=== RUN TestGetArticlesCaseSuccess
23:29:23 | 200 | 28.764333ms | 0.0.0.0 | GET | /api/articles/article1-slug | -
--- PASS: TestGetArticlesCaseSuccess (3.79s)
=== RUN TestCreateArticleCaseSuccess
23:29:27 | 201 | 21.660834ms | 0.0.0.0 | POST | /api/articles | -
--- PASS: TestCreateArticleCaseSuccess (3.75s)
=== RUN TestUpdateArticleCaseSuccess 2025/10/07 23:29:31 /Users/daimor/Projects/golang-fiber-realworld-example-app/store/article.go:85 record not found
[12.349ms] [rows:0] SELECT * FROM "tags" WHERE "tags"."tag" = 'tag3' AND "tags"."deleted_at" IS NULL ORDER BY "tags"."id" LIMIT 1
23:29:31 | 200 | 74.888416ms | 0.0.0.0 | PUT | /api/articles/article1-slug | -
--- PASS: TestUpdateArticleCaseSuccess (3.82s)
=== RUN TestFeedCaseSuccess
23:29:35 | 200 | 103.316875ms | 0.0.0.0 | GET | /api/articles/feed | -
--- PASS: TestFeedCaseSuccess (3.85s)
=== RUN TestDeleteArticleCaseSuccess
23:29:39 | 200 | 32.845667ms | 0.0.0.0 | DELETE | /api/articles/article1-slug | - 2025/10/07 23:29:39 /Users/daimor/Projects/golang-fiber-realworld-example-app/store/article.go:38 record not found
[0.689ms] [rows:0] SELECT * FROM "articles" WHERE ("articles"."slug" = 'article1-slug' AND "articles"."author_id" = 1) AND "articles"."deleted_at" IS NULL ORDER BY "articles"."id" LIMIT 1
23:29:39 | 404 | 885.375µs | 0.0.0.0 | DELETE | /api/articles/article1-slug | -
--- PASS: TestDeleteArticleCaseSuccess (3.78s)
=== RUN TestGetCommentsCaseSuccess
23:29:42 | 200 | 31.516292ms | 0.0.0.0 | GET | /api/articles/article1-slug/comments | -
--- PASS: TestGetCommentsCaseSuccess (3.88s)
=== RUN TestAddCommentCaseSuccess
23:29:46 | 201 | 31.662291ms | 0.0.0.0 | POST | /api/articles/article1-slug/comments | -
--- PASS: TestAddCommentCaseSuccess (3.77s)
=== RUN TestDeleteCommentCaseSuccess
23:29:50 | 200 | 22.555375ms | 0.0.0.0 | DELETE | /api/articles/article1-slug/comments/1 | - 2025/10/07 23:29:50 /Users/daimor/Projects/golang-fiber-realworld-example-app/store/article.go:254 record not found
[0.386ms] [rows:0] SELECT * FROM "comments" WHERE "comments"."id" = 1 AND "comments"."deleted_at" IS NULL ORDER BY "comments"."id" LIMIT 1
23:29:50 | 404 | 474.75µs | 0.0.0.0 | DELETE | /api/articles/article1-slug/comments/1 | -
--- PASS: TestDeleteCommentCaseSuccess (3.71s)
=== RUN TestFavoriteCaseSuccess
23:29:54 | 200 | 51.294125ms | 0.0.0.0 | POST | /api/articles/article1-slug/favorite | -
--- PASS: TestFavoriteCaseSuccess (3.80s)
=== RUN TestUnfavoriteCaseSuccess
23:29:58 | 200 | 44.780459ms | 0.0.0.0 | DELETE | /api/articles/article2-slug/favorite | -
--- PASS: TestUnfavoriteCaseSuccess (3.76s)
=== RUN TestGetTagsCaseSuccess
23:30:01 | 200 | 10.410208ms | 0.0.0.0 | GET | /api/tags | -
--- PASS: TestGetTagsCaseSuccess (3.71s)
=== RUN TestSignUpCaseSuccess
23:30:05 | 201 | 77.083166ms | 0.0.0.0 | POST | /api/users | -
--- PASS: TestSignUpCaseSuccess (3.79s)
=== RUN TestLoginCaseSuccess
23:30:09 | 200 | 89.146833ms | 0.0.0.0 | POST | /api/users/login | -
--- PASS: TestLoginCaseSuccess (3.87s)
=== RUN TestLoginCaseFailed 2025/10/07 23:30:13 /Users/daimor/Projects/golang-fiber-realworld-example-app/store/user.go:33 record not found
[13.172ms] [rows:0] SELECT * FROM "users" WHERE "users"."email" = 'userx@realworld.io' AND "users"."deleted_at" IS NULL ORDER BY "users"."id" LIMIT 1
23:30:13 | 403 | 13.247833ms | 0.0.0.0 | POST | /api/users/login | -
--- PASS: TestLoginCaseFailed (3.74s)
=== RUN TestCurrentUserCaseSuccess
23:30:16 | 200 | 12.081041ms | 0.0.0.0 | GET | /api/user | -
--- PASS: TestCurrentUserCaseSuccess (3.75s)
=== RUN TestCurrentUserCaseInvalid 2025/10/07 23:30:20 /Users/daimor/Projects/golang-fiber-realworld-example-app/store/user.go:22 record not found
[11.931ms] [rows:0] SELECT * FROM "users" WHERE "users"."id" = 100 AND "users"."deleted_at" IS NULL ORDER BY "users"."id" LIMIT 1
23:30:20 | 404 | 12.2145ms | 0.0.0.0 | GET | /api/user | -
--- PASS: TestCurrentUserCaseInvalid (3.74s)
=== RUN TestUpdateUserEmail
23:30:24 | 200 | 33.6815ms | 0.0.0.0 | PUT | /api/user | -
--- PASS: TestUpdateUserEmail (3.81s)
=== RUN TestUpdateUserMultipleField
23:30:28 | 200 | 43.375583ms | 0.0.0.0 | PUT | /api/user | -
--- PASS: TestUpdateUserMultipleField (3.75s)
=== RUN TestGetProfileCaseSuccess 2025/10/07 23:30:32 /Users/daimor/Projects/golang-fiber-realworld-example-app/store/user.go:105 record not found
[17.585ms] [rows:0] SELECT * FROM "follows" WHERE following_id = 1 AND follower_id = 1 ORDER BY "follows"."follower_id" LIMIT 1
23:30:31 | 200 | 53.483292ms | 0.0.0.0 | GET | /api/profiles/user1 | -
--- PASS: TestGetProfileCaseSuccess (3.81s)
=== RUN TestGetProfileCaseNotFound 2025/10/07 23:30:35 /Users/daimor/Projects/golang-fiber-realworld-example-app/store/user.go:44 record not found
[13.039ms] [rows:0] SELECT * FROM "users" WHERE "users"."username" = 'userx' AND "users"."deleted_at" IS NULL ORDER BY "users"."id" LIMIT 1
23:30:35 | 404 | 13.091583ms | 0.0.0.0 | GET | /api/profiles/userx | -
--- PASS: TestGetProfileCaseNotFound (3.72s)
=== RUN TestFollowCaseSuccess
23:30:39 | 200 | 57.295875ms | 0.0.0.0 | POST | /api/profiles/user2/follow | -
--- PASS: TestFollowCaseSuccess (3.84s)
=== RUN TestFollowCaseInvalidUser 2025/10/07 23:30:43 /Users/daimor/Projects/golang-fiber-realworld-example-app/store/user.go:44 record not found
[13.084ms] [rows:0] SELECT * FROM "users" WHERE "users"."username" = 'userx' AND "users"."deleted_at" IS NULL ORDER BY "users"."id" LIMIT 1
23:30:43 | 404 | 13.191708ms | 0.0.0.0 | POST | /api/profiles/userx/follow | -
--- PASS: TestFollowCaseInvalidUser (3.75s)
=== RUN TestUnFollow 2025/10/07 23:30:47 /Users/daimor/Projects/golang-fiber-realworld-example-app/store/user.go:105 record not found
[15.231ms] [rows:0] SELECT * FROM "follows" WHERE following_id = 2 AND follower_id = 1 ORDER BY "follows"."follower_id" LIMIT 1
23:30:47 | 200 | 80.5655ms | 0.0.0.0 | DELETE | /api/profiles/user2/follow | -
--- PASS: TestUnFollow (3.82s)
PASS
ok github.com/alpody/fiber-realworld/handler 91.360s
5. Running the Application with Docker Compose
After confirming that tests pass successfully, the next step is to run the complete Fiber + GORM + IRIS application using Docker.
In this setup, the Go backend is built into a binary, copied into the IRIS container, and started automatically alongside IRIS itself.
This approach makes deployment extremely simple — you can spin up everything with one command.
Updated docker-compose.yml
The project’s modified docker-compose.yml
now defines an iris
service that handles both:
- Running the InterSystems IRIS database.
- Starting the Go Fiber application as part of the same container.
Here’s the key idea:
- The Go app is built using a multistage Docker build.
- The resulting binary is copied into the IRIS image.
- A small init script is included to automatically start the Go app when IRIS launches.
This gives you a self-contained container — a single image that runs both IRIS and your Go web API in perfect sync.
Build and Start the Application
To build the IRIS image and launch the environment, simply run:
docker compose up -d iris --build
This will:
- Build your Go application.
- Create a new IRIS-based Docker image containing the app binary and initialization scripts.
- Start the container in detached mode (
-d
), with IRIS and the Go API running together.
💡 Note:
One of the beautiful aspects of Go is that you’re not limited to embedding your application inside the IRIS container.
Thanks to Go’s single-binary compilation, you can easily build a standalone Docker image for your application — one that connects to InterSystems IRIS over the network using the same connection string.
This approach has two big advantages:
- The resulting image is much smaller, often under 30 MB.
- It cleanly separates application logic from database infrastructure, making it ideal for microservices or cloud deployments.
In production, you can keep IRIS and your Go service in separate containers (or even separate hosts), connected securely through your network — combining IRIS’s reliability with Go’s portability.
6. End-to-End API Testing with Newman
Once your Go + IRIS application is up and running, it’s time to verify that the REST API behaves exactly as expected.
The project includes an additional layer of integration tests — using the Postman / Newman collection from the original RealWorld project.
This ensures that the backend fully complies with the RealWorld API specification and that all endpoints work correctly when backed by InterSystems IRIS.
Newman as a Service
To make testing seamless, the docker-compose.yml
file defines an extra service named newman-checker
.
This service runs the Newman CLI inside a container, executes the full RealWorld API test collection, and connects internally to the running Fiber + IRIS application.
Because both services run inside the same Docker network, the tests can access the backend directly without any extra configuration.
Run the API Tests
To execute the end-to-end tests, simply run:
docker compose run newman-checker
This will:
- Start the Newman container.
- Connect it to the running
iris
service.
- Execute the entire RealWorld API test suite against your Go + IRIS backend.
If everything is set up correctly, you should see a summary like:
[+] Creating 1/1
✔ Container golang-fiber-realworld-example-app-iris-1 Running 0.0s
newman Conduit ❏ Auth
↳ Register
POST http://iris:8585/api/users [201 Created, 327B, 202ms]
┌
│ 'Using "environment" is deprecated. Use "pm.environment" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response contains "user" property
✓ User has "email" property
✓ User has "username" property
✓ User has "bio" property
✓ User has "image" property
✓ User has "token" property ↳ Login
POST http://iris:8585/api/users/login [200 OK, 322B, 119ms]
┌
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response contains "user" property
✓ User has "email" property
✓ User has "username" property
✓ User has "bio" property
✓ User has "image" property
✓ User has "token" property ↳ Login and Remember Token
POST http://iris:8585/api/users/login [200 OK, 322B, 65ms]
┌
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response contains "user" property
✓ User has "email" property
✓ User has "username" property
✓ User has "bio" property
✓ User has "image" property
✓ User has "token" property
✓ Global variable "token" has been set ↳ Current User
GET http://iris:8585/api/user [200 OK, 322B, 20ms]
┌
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response contains "user" property
✓ User has "email" property
✓ User has "username" property
✓ User has "bio" property
✓ User has "image" property
✓ User has "token" property ↳ Update User
PUT http://iris:8585/api/user [200 OK, 318B, 16ms]
┌
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response contains "user" property
✓ User has "email" property
✓ User has "username" property
✓ User has "bio" property
✓ User has "image" property
✓ User has "token" property ❏ Articles
↳ All Articles
GET http://iris:8585/api/articles [200 OK, 141B, 29ms]
┌
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "articles" property
✓ Response contains "articlesCount" property
✓ articlesCount is an integer
✓ articlesCount is 0 when feed is empty ↳ Articles by Author
GET http://iris:8585/api/articles?author=johnjacob [200 OK, 141B, 2ms]
┌
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "articles" property
✓ Response contains "articlesCount" property
✓ articlesCount is an integer
✓ articlesCount is 0 when feed is empty ↳ Articles Favorited by Username
GET http://iris:8585/api/articles?favorited=user2021 [200 OK, 141B, 7ms]
┌
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "articles" property
✓ Response contains "articlesCount" property
✓ articlesCount is an integer
✓ articlesCount is 0 when feed is empty ↳ Articles by Tag
GET http://iris:8585/api/articles?tag=dragons [200 OK, 141B, 8ms]
┌
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "articles" property
✓ Response contains "articlesCount" property
✓ articlesCount is an integer
✓ articlesCount is 0 when feed is empty ❏ Articles, Favorite, Comments
↳ Create Article
POST http://iris:8585/api/articles [201 Created, 479B, 216ms]
┌
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response contains "article" property
✓ Article has "title" property
✓ Article has "slug" property
✓ Article has "body" property
✓ Article has "createdAt" property
✓ Article's "createdAt" property is an ISO 8601 timestamp
✓ Article has "updatedAt" property
✓ Article's "updatedAt" property is an ISO 8601 timestamp
✓ Article has "description" property
✓ Article has "tagList" property
✓ Article's "tagList" property is an Array
✓ Article has "author" property
✓ Article has "favorited" property
✓ Article has "favoritesCount" property
✓ favoritesCount is an integer ↳ Feed
GET http://iris:8585/api/articles/feed [200 OK, 141B, 14ms]
┌
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "articles" property
✓ Response contains "articlesCount" property
✓ articlesCount is an integer
✓ articlesCount is 0 when feed is empty ↳ All Articles
GET http://iris:8585/api/articles [200 OK, 495B, 28ms]
┌
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "articles" property
✓ Response contains "articlesCount" property
✓ articlesCount is an integer
✓ Article has "title" property
✓ Article has "slug" property
✓ Article has "createdAt" property
✓ Article's "createdAt" property is an ISO 8601 timestamp
✓ Article has "updatedAt" property
✓ Article's "updatedAt" property is an ISO 8601 timestamp
✓ Article has "description" property
✓ Article has "tagList" property
✓ Article's "tagList" property is an Array
✓ Article has "author" property
✓ Article has "favorited" property
✓ Article has "favoritesCount" property
✓ favoritesCount is an integer ↳ All Articles with auth
GET http://iris:8585/api/articles [200 OK, 495B, 3ms]
┌
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "articles" property
✓ Response contains "articlesCount" property
✓ articlesCount is an integer
✓ Article has "title" property
✓ Article has "slug" property
✓ Article has "createdAt" property
✓ Article's "createdAt" property is an ISO 8601 timestamp
✓ Article has "updatedAt" property
✓ Article's "updatedAt" property is an ISO 8601 timestamp
✓ Article has "description" property
✓ Article has "tagList" property
✓ Article's "tagList" property is an Array
✓ Article has "author" property
✓ Article has "favorited" property
✓ Article has "favoritesCount" property
✓ favoritesCount is an integer ↳ Articles by Author
GET http://iris:8585/api/articles?author=user2021 [200 OK, 495B, 4ms]
┌
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "articles" property
✓ Response contains "articlesCount" property
✓ articlesCount is an integer
✓ Article has "title" property
✓ Article has "slug" property
✓ Article has "createdAt" property
✓ Article's "createdAt" property is an ISO 8601 timestamp
✓ Article has "updatedAt" property
✓ Article's "updatedAt" property is an ISO 8601 timestamp
✓ Article has "description" property
✓ Article has "tagList" property
✓ Article's "tagList" property is an Array
✓ Article has "author" property
✓ Article has "favorited" property
✓ Article has "favoritesCount" property
✓ favoritesCount is an integer ↳ Articles by Author with auth
GET http://iris:8585/api/articles?author=user2021 [200 OK, 495B, 4ms]
┌
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "articles" property
✓ Response contains "articlesCount" property
✓ articlesCount is an integer
✓ Article has "title" property
✓ Article has "slug" property
✓ Article has "createdAt" property
✓ Article's "createdAt" property is an ISO 8601 timestamp
✓ Article has "updatedAt" property
✓ Article's "updatedAt" property is an ISO 8601 timestamp
✓ Article has "description" property
✓ Article has "tagList" property
✓ Article's "tagList" property is an Array
✓ Article has "author" property
✓ Article has "favorited" property
✓ Article has "favoritesCount" property
✓ favoritesCount is an integer ↳ Single Article by slug
GET http://iris:8585/api/articles/how-to-train-your-dragon [200 OK, 474B, 19ms]
┌
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response contains "article" property
✓ Article has "title" property
✓ Article has "slug" property
✓ Article has "body" property
✓ Article has "createdAt" property
✓ Article's "createdAt" property is an ISO 8601 timestamp
✓ Article has "updatedAt" property
✓ Article's "updatedAt" property is an ISO 8601 timestamp
✓ Article has "description" property
✓ Article has "tagList" property
✓ Article's "tagList" property is an Array
✓ Article has "author" property
✓ Article has "favorited" property
✓ Article has "favoritesCount" property
✓ favoritesCount is an integer ↳ Articles by Tag
GET http://iris:8585/api/articles?tag=dragons [200 OK, 495B, 3ms]
┌
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "articles" property
✓ Response contains "articlesCount" property
✓ articlesCount is an integer
✓ An article was returned
✓ Article has "title" property
✓ Article has "slug" property
✓ Article has "createdAt" property
✓ Article's "createdAt" property is an ISO 8601 timestamp
✓ Article has "updatedAt" property
✓ Article's "updatedAt" property is an ISO 8601 timestamp
✓ Article has "description" property
✓ Article has "tagList" property
✓ Article's "tagList" property is an Array
✓ The first tag is dragons
✓ The second tag is training
✓ Article has "author" property
✓ Article has "favorited" property
✓ Article has "favoritesCount" property
✓ favoritesCount is an integer ↳ Update Article
PUT http://iris:8585/api/articles/how-to-train-your-dragon [200 OK, 453B, 52ms]
┌
│ 'Using "environment" is deprecated. Use "pm.environment" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response contains "article" property
✓ Article has "title" property
✓ Article has "slug" property
✓ Article has "body" property
✓ Article has "createdAt" property
✓ Article's "createdAt" property is an ISO 8601 timestamp
✓ Article has "updatedAt" property
✓ Article's "updatedAt" property is an ISO 8601 timestamp
✓ Article has "description" property
✓ Article has "tagList" property
✓ Article's "tagList" property is an Array
✓ Article has "author" property
✓ Article has "favorited" property
✓ Article has "favoritesCount" property
✓ favoritesCount is an integer ↳ Favorite Article
POST http://iris:8585/api/articles/how-to-train-your-dragon/favorite [200 OK, 454B, 51ms]
┌
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response contains "article" property
✓ Article has "title" property
✓ Article has "slug" property
✓ Article has "body" property
✓ Article has "createdAt" property
✓ Article's "createdAt" property is an ISO 8601 timestamp
✓ Article has "updatedAt" property
✓ Article's "updatedAt" property is an ISO 8601 timestamp
✓ Article has "description" property
✓ Article has "tagList" property
✓ Article's "tagList" property is an Array
✓ Article has "author" property
✓ Article has "favorited" property
✓ Article's 'favorited' property is true
✓ Article has "favoritesCount" property
✓ favoritesCount is an integer
✓ Article's 'favoritesCount' property is greater than 0 ↳ Articles Favorited by Username
GET http://iris:8585/api/articles?favorited=user2021 [200 OK, 470B, 3ms]
┌
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "articles" property
✓ Response contains "articlesCount" property
✓ articlesCount is an integer
✓ Article has "title" property
✓ Article has "slug" property
✓ Article has "createdAt" property
✓ Article's "createdAt" property is an ISO 8601 timestamp
✓ Article has "updatedAt" property
✓ Article's "updatedAt" property is an ISO 8601 timestamp
✓ Article has "description" property
✓ Article has "tagList" property
✓ Article's "tagList" property is an Array
✓ Article has "author" property
✓ Article has "favorited" property
✓ Article has "favoritesCount" property
✓ favoritesCount is 1 ↳ Articles Favorited by Username with auth
GET http://iris:8585/api/articles?favorited=user2021 [200 OK, 470B, 4ms]
┌
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "articles" property
✓ Response contains "articlesCount" property
✓ articlesCount is an integer
✓ Article has "title" property
✓ Article has "slug" property
✓ Article has "createdAt" property
✓ Article's "createdAt" property is an ISO 8601 timestamp
✓ Article has "updatedAt" property
✓ Article's "updatedAt" property is an ISO 8601 timestamp
✓ Article has "description" property
✓ Article has "tagList" property
✓ Article's "tagList" property is an Array
✓ Article has "author" property
✓ Article has "favorited" property
✓ Article has "favoritesCount" property
✓ favoritesCount is 1 ↳ Unfavorite Article
DELETE http://iris:8585/api/articles/how-to-train-your-dragon/favorite [200 OK, 449B, 13ms]
┌
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response contains "article" property
✓ Article has "title" property
✓ Article has "slug" property
✓ Article has "body" property
✓ Article has "createdAt" property
✓ Article's "createdAt" property is an ISO 8601 timestamp
✓ Article has "updatedAt" property
✓ Article's "updatedAt" property is an ISO 8601 timestamp
✓ Article has "description" property
✓ Article has "tagList" property
✓ Article's "tagList" property is an Array
✓ Article has "author" property
✓ Article has "favorited" property
✓ Article has "favoritesCount" property
✓ favoritesCount is an integer
✓ Article's "favorited" property is false ↳ Create Comment for Article
POST http://iris:8585/api/articles/how-to-train-your-dragon/comments [201 Created, 313B, 50ms]
┌
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response contains "comment" property
✓ Comment has "id" property
✓ Comment has "body" property
✓ Comment has "createdAt" property
✓ "createdAt" property is an ISO 8601 timestamp
✓ Comment has "updatedAt" property
✓ "updatedAt" property is an ISO 8601 timestamp
✓ Comment has "author" property ↳ All Comments for Article
GET http://iris:8585/api/articles/how-to-train-your-dragon/comments [200 OK, 311B, 23ms]
┌
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "comments" property
✓ Comment has "id" property
✓ Comment has "body" property
✓ Comment has "createdAt" property
✓ "createdAt" property is an ISO 8601 timestamp
✓ Comment has "updatedAt" property
✓ "updatedAt" property is an ISO 8601 timestamp
✓ Comment has "author" property ↳ All Comments for Article without login
GET http://iris:8585/api/articles/how-to-train-your-dragon/comments [200 OK, 311B, 2ms]
┌
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "comments" property
✓ Comment has "id" property
✓ Comment has "body" property
✓ Comment has "createdAt" property
✓ "createdAt" property is an ISO 8601 timestamp
✓ Comment has "updatedAt" property
✓ "updatedAt" property is an ISO 8601 timestamp
✓ Comment has "author" property ↳ Delete Comment for Article
DELETE http://iris:8585/api/articles/how-to-train-your-dragon/comments/1 [200 OK, 123B, 27ms] ↳ Delete Article
DELETE http://iris:8585/api/articles/how-to-train-your-dragon [200 OK, 123B, 15ms] ❏ Profiles
↳ Register Celeb
POST http://iris:8585/api/users [201 Created, 339B, 65ms]
┌
│ 'Using "environment" is deprecated. Use "pm.environment" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response contains "user" property
✓ User has "email" property
✓ User has "username" property
✓ User has "bio" property
✓ User has "image" property
✓ User has "token" property ↳ Profile
GET http://iris:8585/api/profiles/celeb_user2021 [200 OK, 191B, 30ms]
┌
│ 'Using "environment" is deprecated. Use "pm.environment" instead.'
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "profile" property
✓ Profile has "username" property
✓ Profile has "bio" property
✓ Profile has "image" property
✓ Profile has "following" property ↳ Follow Profile
POST http://iris:8585/api/profiles/celeb_user2021/follow [200 OK, 190B, 32ms]
┌
│ 'Using "environment" is deprecated. Use "pm.environment" instead.'
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "profile" property
✓ Profile has "username" property
✓ Profile has "bio" property
✓ Profile has "image" property
✓ Profile has "following" property
✓ Profile's "following" property is true ↳ Unfollow Profile
DELETE http://iris:8585/api/profiles/celeb_user2021/follow [200 OK, 191B, 47ms]
┌
│ 'Using "environment" is deprecated. Use "pm.environment" instead.'
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "profile" property
✓ Profile has "username" property
✓ Profile has "bio" property
✓ Profile has "image" property
✓ Profile has "following" property
✓ Profile's "following" property is false ❏ Tags
↳ All Tags
GET http://iris:8585/api/tags [200 OK, 139B, 13ms]
┌
│ 'Using "responseCode" is deprecated. Use "pm.response.code" instead.'
│ 'Using "tests" is deprecated. Use "pm.test()" instead.'
└
✓ Response code is 200 OK
✓ Response contains "tags" property
✓ "tags" property returned as array ┌─────────────────────────┬───────────────────┬──────────────────┐
│ │ executed │ failed │
├─────────────────────────┼───────────────────┼──────────────────┤
│ iterations │ 1 │ 0 │
├─────────────────────────┼───────────────────┼──────────────────┤
│ requests │ 32 │ 0 │
├─────────────────────────┼───────────────────┼──────────────────┤
│ test-scripts │ 48 │ 0 │
├─────────────────────────┼───────────────────┼──────────────────┤
│ prerequest-scripts │ 18 │ 0 │
├─────────────────────────┼───────────────────┼──────────────────┤
│ assertions │ 311 │ 0 │
├─────────────────────────┴───────────────────┴──────────────────┤
│ total run duration: 1824ms │
├────────────────────────────────────────────────────────────────┤
│ total data received: 6.77kB (approx) │
├────────────────────────────────────────────────────────────────┤
│ average response time: 37ms [min: 2ms, max: 216ms, s.d.: 50ms] │
└────────────────────────────────────────────────────────────────┘
What This Confirms
Passing the Newman suite means your Go + Fiber + GORM + IRIS stack is fully compatible with the RealWorld API spec —
a great indicator that your backend logic, ORM integration, and database connectivity all work as expected.
It’s not just a demo anymore — it’s a production-grade, spec-compliant backend, powered by InterSystems IRIS.
7. Explore the API with Swagger UI
Once everything is up and running, you can finally explore the live REST API through a clean, interactive interface.
The project comes with a pre-generated Swagger UI, making it easy to inspect and test endpoints directly in your browser.
After starting the application, open:
👉 http://localhost:8585/swagger/index.html
You’ll see the full RealWorld API specification — all endpoints powered by your Go Fiber backend, connected through GORM to InterSystems IRIS.
From here, you can:
- Register and log in users
- Create, edit, and delete articles
- Post comments
- Follow or unfollow users
All the requests you send are processed in real time by IRIS, through the new Go driver and ORM integration.
.png)
What’s Next
You’ve now built and run a complete Go + Fiber + GORM + IRIS backend —
with automated tests, Swagger documentation, and containerized deployment.
From here, you can:
- Extend the app with your own features.
- Deploy IRIS and your Go app as separate services for scalability.
- Experiment with advanced IRIS capabilities — globals, analytics, and interoperability.
This demo shows that InterSystems IRIS can be a first-class citizen in the modern Go ecosystem —
powerful, fast, and ready for cloud-native applications.
This project is participating in the contest, please vote here.