Bringing It All Together: Go, GORM, and InterSystems IRIS in Action
Since we reached two important milestones for Go developers working with InterSystems IRIS:
- The Wait Is Over: Welcome GoLang Support for InterSystems IRIS — where we unveiled the new go-irisnative driver, providing a native
database/sqlinterface for Go. - GORM Meets InterSystems IRIS: Introducing gorm-iris — where we showed how to integrate IRIS with GORM, one of the most popular Go ORM libraries.
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-app2. 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
swagtool for generating Swagger documentation. - Execute the Go
generatecommand, 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
funcTestDB(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), // io writer
logger.Config{
SlowThreshold: time.Second, // Slow SQL threshold
LogLevel: logger.Error, // Log level
Colorful: true, // Disable color
},
)
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
}
funcDropTestDB()error {
if container != nil {
container.Terminate(context.Background())
}
container = nilreturnnil
}
funcAutoMigrate(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
)
funcTestMain(m *testing.M) {
flag.BoolVar(&useContainer, "container", true, "Use container image.")
flag.Parse()
// setup()
code := m.Run()
// tearDown()
os.Exit(code)
}
funcsetup() {
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
useContaineristrue, the function launches a new IRIS container viatestcontainers-iris-go.- It creates a clean environment with custom credentials (
testuser/testpassword) and a namespace calledTEST. - The connection string is retrieved automatically via
container.MustConnectionString(ctx).
- It creates a clean environment with custom credentials (
- When running locally without containers, the code connects to a pre-existing IRIS instance and ensures the
TESTdatabase 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 -vflag -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:
Tests result
=== 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.360s5. 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 --buildThis 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-checkerThis will:
- Start the Newman container.
- Connect it to the running
irisservice. - Execute the entire RealWorld API test suite against your Go + IRIS backend.
If everything is set up correctly, you should see a summary like:
Newman tests result
[+] 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.
Comments
Nice work!