{"id":13468129,"url":"https://github.com/vapor/postgres-nio","last_synced_at":"2026-02-20T11:01:25.676Z","repository":{"id":34464504,"uuid":"150622661","full_name":"vapor/postgres-nio","owner":"vapor","description":"🐘 Non-blocking, event-driven Swift client for PostgreSQL.","archived":false,"fork":false,"pushed_at":"2025-05-12T15:15:34.000Z","size":1264,"stargazers_count":354,"open_issues_count":70,"forks_count":80,"subscribers_count":21,"default_branch":"main","last_synced_at":"2025-05-12T16:32:15.339Z","etag":null,"topics":["postgresql","server-side-swift","swift","swiftnio","vapor"],"latest_commit_sha":null,"homepage":"https://api.vapor.codes/postgresnio/documentation/postgresnio/","language":"Swift","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/vapor.png","metadata":{"funding":{"github":["vapor"],"open_collective":"vapor"},"files":{"readme":"README.md","changelog":null,"contributing":".github/contributing.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-09-27T17:18:01.000Z","updated_at":"2025-05-12T15:15:38.000Z","dependencies_parsed_at":"2023-10-16T23:58:36.269Z","dependency_job_id":"78245879-7bbe-4483-aa62-3538c6a08140","html_url":"https://github.com/vapor/postgres-nio","commit_stats":{"total_commits":383,"total_committers":43,"mean_commits":8.906976744186046,"dds":0.5509138381201044,"last_synced_commit":"f2a6394a2e7157d547727b975fc0328b92f89fb1"},"previous_names":[],"tags_count":81,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vapor%2Fpostgres-nio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vapor%2Fpostgres-nio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vapor%2Fpostgres-nio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vapor%2Fpostgres-nio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vapor","download_url":"https://codeload.github.com/vapor/postgres-nio/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254042818,"owners_count":22004907,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["postgresql","server-side-swift","swift","swiftnio","vapor"],"created_at":"2024-07-31T15:01:05.972Z","updated_at":"2026-02-20T11:01:25.670Z","avatar_url":"https://github.com/vapor.png","language":"Swift","funding_links":["https://github.com/sponsors/vapor","https://opencollective.com/vapor"],"categories":["Swift"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://design.vapor.codes/images/vapor-postgresnio.svg\" height=\"96\" alt=\"PostgresNIO\"\u003e\n\u003cbr\u003e\n\u003cbr\u003e\n\u003ca href=\"https://api.vapor.codes/postgresnio/documentation/postgresnio/\"\u003e\n    \u003cimg src=\"https://design.vapor.codes/images/readthedocs.svg\" alt=\"Documentation\"\u003e\n\u003c/a\u003e\n\u003ca href=\"LICENSE\"\u003e\n    \u003cimg src=\"https://design.vapor.codes/images/mitlicense.svg\" alt=\"MIT License\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/vapor/postgres-nio/actions/workflows/test.yml\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/actions/workflow/status/vapor/postgres-nio/test.yml?event=push\u0026style=plastic\u0026logo=github\u0026label=tests\u0026logoColor=%23ccc\" alt=\"Continuous Integration\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://swift.org\"\u003e\n    \u003cimg src=\"https://design.vapor.codes/images/swift60up.svg\" alt=\"Swift 6.0+\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://www.swift.org/sswg/incubation-process.html\"\u003e\n    \u003cimg src=\"https://design.vapor.codes/images/sswg-graduated.svg\" alt=\"SSWG Incubation Level: Graduated\"\u003e\n\u003c/a\u003e\n\u003c/p\u003e\n\n🐘 Non-blocking, event-driven Swift client for PostgreSQL built on [SwiftNIO].\n\nFeatures:\n\n- A [`PostgresConnection`] which allows you to connect to, authorize with, query, and retrieve results from a PostgreSQL server\n- A [`PostgresClient`] which pools and manages connections \n- An async/await interface that supports backpressure \n- Automatic conversions between Swift primitive types and the Postgres wire format\n- Integrated with the Swift server ecosystem, including use of [SwiftLog] and [ServiceLifecycle].\n- Designed to run efficiently on all supported platforms (tested extensively on Linux and Darwin systems)\n- Support for `Network.framework` when available (e.g. on Apple platforms)\n- Supports running on Unix Domain Sockets\n\n## API Docs\n\nCheck out the [PostgresNIO API docs][Documentation] for a \ndetailed look at all of the classes, structs, protocols, and more.\n\n## Getting started\n\nInterested in an example? We prepared a simple [Birthday example](https://github.com/vapor/postgres-nio/blob/main/Snippets/Birthdays.swift)\nin the Snippets folder.\n\n#### Adding the dependency\n\nAdd `PostgresNIO` as dependency to your `Package.swift`:\n\n```swift\n  dependencies: [\n    .package(url: \"https://github.com/vapor/postgres-nio.git\", from: \"1.21.0\"),\n    ...\n  ]\n```\n\nAdd `PostgresNIO` to the target you want to use it in:\n```swift\n  targets: [\n    .target(name: \"MyFancyTarget\", dependencies: [\n      .product(name: \"PostgresNIO\", package: \"postgres-nio\"),\n    ])\n  ]\n```\n\n#### Creating a client\n\nTo create a [`PostgresClient`], which pools connections for you, first create a configuration object:\n\n```swift\nimport PostgresNIO\n\nlet config = PostgresClient.Configuration(\n  host: \"localhost\",\n  port: 5432,\n  username: \"my_username\",\n  password: \"my_password\",\n  database: \"my_database\",\n  tls: .disable\n)\n```\n\nNext you can create you client with it:\n```swift\nlet client = PostgresClient(configuration: config)\n```\n\nOnce you have create your client, you must [`run()`] it:\n```swift\nawait withTaskGroup(of: Void.self) { taskGroup in\n    taskGroup.addTask {\n        await client.run() // !important\n    }\n\n    // You can use the client while the `client.run()` method is not cancelled.\n\n    // To shutdown the client, cancel its run method, by cancelling the taskGroup.\n    taskGroup.cancelAll()\n}\n```\n\n#### Querying\n\nOnce a client is running, queries can be sent to the server. This is straightforward:\n\n```swift\nlet rows = try await client.query(\"SELECT id, username, birthday FROM users\")\n```\n\nThe query will return a [`PostgresRowSequence`], which is an AsyncSequence of [`PostgresRow`]s. \nThe rows can be iterated one-by-one: \n\n```swift\nfor try await row in rows {\n  // do something with the row\n}\n```\n\n#### Decoding from PostgresRow\n\nHowever, in most cases it is much easier to request a row's fields as a set of Swift types:\n\n```swift\nfor try await (id, username, birthday) in rows.decode((Int, String, Date).self) {\n  // do something with the datatypes.\n}\n```\n\nA type must implement the [`PostgresDecodable`] protocol in order to be decoded from a row. PostgresNIO provides default implementations for most of Swift's builtin types, as well as some types provided by Foundation:\n\n- `Bool`\n- `Bytes`, `Data`, `ByteBuffer`\n- `Date`\n- `UInt8`, `Int16`, `Int32`, `Int64`, `Int`\n- `Float`, `Double`\n- `String`\n- `UUID`\n\n#### Querying with parameters\n\nSending parameterized queries to the database is also supported (in the coolest way possible):\n\n```swift\nlet id = 1\nlet username = \"fancyuser\"\nlet birthday = Date()\ntry await client.query(\"\"\"\n  INSERT INTO users (id, username, birthday) VALUES (\\(id), \\(username), \\(birthday))\n  \"\"\", \n  logger: logger\n)\n```\n\nWhile this looks at first glance like a classic case of [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) 😱, PostgresNIO's API ensures that this usage is safe. The first parameter of the [`query(_:logger:)`] method is not a plain `String`, but a [`PostgresQuery`], which implements Swift's `ExpressibleByStringInterpolation` protocol. PostgresNIO uses the literal parts of the provided string as the SQL query and replaces each interpolated value with a parameter binding. Only values which implement the [`PostgresEncodable`] protocol may be interpolated in this way. As with [`PostgresDecodable`], PostgresNIO provides default implementations for most common types.\n\nSome queries do not receive any rows from the server (most often `INSERT`, `UPDATE`, and `DELETE` queries with no `RETURNING` clause, not to mention most DDL queries). To support this, the [`query(_:logger:)`] method is marked `@discardableResult`, so that the compiler does not issue a warning if the return value is not used. \n\n## Security\n\nPlease see [SECURITY.md] for details on the security process.\n\n[SSWG Incubation]: https://github.com/swift-server/sswg/blob/main/process/incubation.md#graduated-level\n[Documentation]: https://api.vapor.codes/postgresnio/documentation/postgresnio\n[Team Chat]: https://discord.gg/vapor\n[MIT License]: LICENSE\n[Continuous Integration]: https://github.com/vapor/postgres-nio/actions\n[Swift 6.0]: https://swift.org\n[Security.md]: https://github.com/vapor/.github/blob/main/SECURITY.md\n\n[`PostgresConnection`]: https://api.vapor.codes/postgresnio/documentation/postgresnio/postgresconnection\n[`PostgresClient`]: https://api.vapor.codes/postgresnio/documentation/postgresnio/postgresclient\n[`run()`]: https://api.vapor.codes/postgresnio/documentation/postgresnio/postgresclient/run()\n[`query(_:logger:)`]: https://api.vapor.codes/postgresnio/documentation/postgresnio/postgresconnection/query(_:logger:file:line:)-9mkfn\n[`PostgresQuery`]: https://api.vapor.codes/postgresnio/documentation/postgresnio/postgresquery\n[`PostgresRow`]: https://api.vapor.codes/postgresnio/documentation/postgresnio/postgresrow\n[`PostgresRowSequence`]: https://api.vapor.codes/postgresnio/documentation/postgresnio/postgresrowsequence\n[`PostgresDecodable`]: https://api.vapor.codes/postgresnio/documentation/postgresnio/postgresdecodable\n[`PostgresEncodable`]: https://api.vapor.codes/postgresnio/documentation/postgresnio/postgresencodable\n[SwiftNIO]: https://github.com/apple/swift-nio\n[PostgresKit]: https://github.com/vapor/postgres-kit\n[SwiftLog]: https://github.com/apple/swift-log\n[ServiceLifecycle]: https://github.com/swift-server/swift-service-lifecycle\n[`Logger`]: https://apple.github.io/swift-log/docs/current/Logging/Structs/Logger.html\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvapor%2Fpostgres-nio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvapor%2Fpostgres-nio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvapor%2Fpostgres-nio/lists"}