Nutrient

Home

SDK

Software Development Kits

Low-Code

IT Document Solutions

Workflow

Workflow Automation Platform

DWS API

Document Web Services

T
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Company

About

Team

Careers

Contact

Security

Partners

Legal

Resources

Blog

Events

Try for free

Contact Sales
Contact sales
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

products

Web

Web

Document Authoring

AI Assistant

Salesforce

Mobile

iOS

Android

visionOS

Flutter

React Native

MAUI

Server

Document Engine

Document Converter Services

.NET

Java

Node.js

AIDocument Processing

All products

solutions

USECASES

Viewing

Editing

OCR and Data Extraction

Signing

Forms

Scanning & Barcodes

Markup

Generation

Document Conversion

Redaction

Intelligent Doc. Processing

Collaboration

Authoring

Security

INdustries

Aviation

Construction

Education

Financial Services

Government

Healthcare

Legal

Life Sciences

All Solutions

Docs

Guides overview

Web

AIAssistant

Document Engine

iOS

Android

visionOS

Java

Node.js

.NET

Document Converter Services

Downloads

Demo

Support

Log in

Resources

Blog

Events

Pricing

Try for free

Free Trial

Company

About

Security

Partners

Legal

Contact Sales
Contact Sales
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

products

Products overview

Document Converter

Document Editor

Document Searchability

Document Automation Server

Integrations

SharePoint

Power Automate

Nintex

OneDrive

Teams

Window Servers

solutions

USECASES

Conversion

Editing

OCR Data Extraction

Tagging

Security Compliance

Workflow Automation

Solutions For

Overview

Legal

Public Sector

Finance

All Solutions

resources

Help center

Document Converter

Document Editor

Document Searchability

Document Automation Server

learn

Blog

Customer stories

Events

Support

Log in

Pricing

Try for free

Company

About

Security

Partners

Legal

Contact Sales
Contact Sales
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Product

Product overview

Process Builder

Form Designer

Document Viewer

Office Templating

Customization

Reporting

solutions

Industries

Healthcare

Financial

Manufacturing

Pharma

Education

Construction

Nonprofit

Local Government

Food and Beverage

Departments

ITServices

Finance

Compliance

Human Resources

Sales

Marketing

Services

Overview

Capex-accelerator

Process Consulting

Workflow Prototype

All Solutions

resources

Help center

guides

Admin guides

End user guides

Workflow templates

Form templates

Training

learn

Blog

Customer stories

Events

Support

Pricing

Support

Company

About

Security

Partners

Legal

Try for Free
Contact Sales
Try for Free
Contact Sales
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Services

Generation

Editing

Conversion

Watermarking

OCR

Table Extraction

Pricing

Docs

Log in

Try for Free
Try for Free

Free trial

Blog post

A Peek at Our CD Pipeline

Reinhard Hafenscher Reinhard Hafenscher

Table of contents

  • Hello World
  • Shipping Containers
  • Putting It Together
  • Conclusion
Illustration: A Peek at Our CD Pipeline

Today I want to give you a peek behind the curtain and walk you through how we set up our continuous deployment (CD) pipeline for PSPDFKit API. More specifically, I’ll talk about which tools we used and how we structured our deployment workflow. So, let’s get started.

Hello World

All our PSPDFKit API infrastructure is hosted on AWS, and the first step in making our CD pipeline work was to choose a tool to define our infrastructure. With AWS, the first choice might be CloudFormation, as it’s an AWS-native way of provisioning the infrastructure. However, since we already had experience managing our CI infrastructure with Terraform, we decided that would be the way to go.

With the tool selected, all we needed to do was set up all the AWS resources required to run. The details of this aren’t relevant to the CD setup itself. What matters is that by using Terraform, we can check if a pull request changes any part of our deployed infrastructure, and if so, we can apply the changes automatically.

Shipping Containers

Infrastructure is one half of the equation, and the other half is deploying is our actual code. For PSPDFKit API, we make use of ECS, which means we have to build Docker images. Luckily for us, this is something we have a lot of experience with, since PSPDFKit Server and PSPDFKit Processor are shipped as Docker images.

There isn’t any magic here; we just have a Dockerfile for each of our services that installs the dependencies needed, builds the code, and sets up the entry point.

For our CD pipeline, all we need to do is wrap each process in a job we can run on CI and then upload the resulting image to our registry. Then, when our ECS tasks start, they pull the latest image from the registry. One thing to note here is that PSPDFKit API is actually composed of multiple different services working together — something we can make use of later to improve the turnaround time of our CD pipeline.

Putting It Together

Now this is where it gets interesting. We use Buildkite for our CI, so the final step is to put things together in a way that makes sense. One of the powerful things about Buildkite is that you can dynamically generate your pipeline on demand. For this, we have a Ruby script, and we use it to do the following:

  1. First, we check if there were any changes to our infrastructure by running terraform plan. When running plan, Terraform will detect all changes between the deployed infrastructure and the infrastructure defined locally. In our case, this encompasses both actual infrastructure changes and changes to the Docker image used (since we tag each image with the Git SHA we built it from, causing it to be marked as a change). For this reason, we explicitly first try running terraform plan with the currently deployed image tag to determine if there are infrastructure changes or only code changes.

  2. Next, we check if any of our services needs to be updated. We do this by generating a Git diff of the commit being deployed (in our case, the latest master merge) and the last successfully deployed commit. Then, we check if any of the changed files are part of any of our deployed services. Since we have a monorepo, this is needed to filter out unrelated changes and prevent useless deployments from running.

  3. Finally, once we’ve determined what parts of the pipeline need to run, we can assemble it.

This is run for every merge to master. We also make use of concurrency groups to ensure that all merges to master are deployed in order, and that only one job is touching our infrastructure at any one time.

The Final Pipeline

Here’s how the final pipeline looks, including all the steps that can optionally be skipped:

  • If there are code changes, we build our services. Here, we take advantage of the fact that we split PSPDFKit API into multiple smaller services. This allows us to only build and deploy the services that actually changed, in turn speeding up the deployment.

    • This step not only builds a release-ready Docker image, but it also runs the full test suite to prevent concurrent merges from introducing errors on master.

    • It also pushes our built images to our internal Docker registry tagged with the current Git SHA.

We run two full deployments of PSPDFKit API: a staging one and a production one. Our CD pipeline always runs for the staging deployment first, and then, if there are no errors, for the production deployment.

  • If we’re in production and we find infrastructure changes, we require a manual unblock step before deployment. Otherwise, the whole pipeline runs automatically.

  • Once we’re ready to run, we update our deployed infrastructure. This also updates our ECS task used for database (DB) migrations.

  • Then, we run any DB migrations that have been introduced since the last successful deployment. Part of this also entails enabling and disabling feature flags, which allows us to merge and test features on staging without affecting production.

  • Finally, we deploy the latest version of our services that we built in the first step.

Here are the concrete steps we took to make this fast:

  • Only deploy what you need. We spent a lot of time ensuring that our deployment pipeline skips all steps that aren’t needed.

  • Keep tests fast. We recently wrote about the benefits of keeping CI fast, and the same idea applies here. Making your test suite fast for PRs also makes your deployment fast.

  • Skip steps that don’t matter. While each PR needs to make sure the committed code is formatted and passes the linter and any other static checks, these steps aren’t needed in the deployment pipeline, and skipping them can shave off valuable seconds.

  • Use the right tools. Terraform is incredibly fast at both checking if there are changes and applying them, often taking less than a minute to do this with our entire infrastructure.

Conclusion

While this only scraped the surface of our setup, I hope it still serves as useful inspiration for determining what can be done and where you have the potential for optimization. Ultimately, a continuous deployment pipeline is a unique as the product it’s built for, and there’s no one-size-fits-all approach, but the general ideas still apply.

Explore related topics

API Insights Development
Free trial Ready to get started?
Free trial

Related articles

Explore more
CLOUDAPI

Nutrient DWS MCP Server — Create and edit documents with natural language

CLOUDSOLUTIONSAPIAIRedaction

From black boxes to smart blurs: AI redaction sets a new document security baseline in DWS Processor API

SDKDEVELOPMENTZapierAPI

Introducing the Nutrient Document Web Services API on Zapier

Company
About
Security
Team
Careers
We're hiring
Partners
Legal
Products
SDK
Low-Code
Workflow
DWS API
resources
Blog
Events
Customer Stories
Tutorials
News
connect
Contact
LinkedIn
YouTube
Discord
X
Facebook
Popular
Java PDF Library
Tag Text
PDF SDK Viewer
Tag Text
React Native PDF SDK
Tag Text
PDF SDK
Tag Text
iOS PDF Viewer
Tag Text
PDF Viewer SDK/Library
Tag Text
PDF Generation
Tag Text
SDK
Web
Tag Text
Mobile/VR
Tag Text
Server
Tag Text
Use Cases
Tag Text
Industries
Tag Text
Resources
Blog
Tag Text
Events
Customer Stories
Tag Text
Tutorials
Tag Text
Features List
Tag Text
Compare
Tag Text
community
Free Trial
Tag Text
Documentation
Tag Text
Nutrient Portal
Tag Text
Contact Support
Tag Text
Company
About
Tag Text
Security
Tag Text
Careers
Tag Text
Legal
Tag Text
Pricing
Tag Text
Partners
Tag Text
connect
Contact
Tag Text
LinkedIn
Tag Text
YouTube
Tag Text
Discord
Tag Text
X
Tag Text
Facebook
Tag Text
low-code
Document Converter
Tag Text
Document Editor
Tag Text
Document Automation Server
Tag Text
Document Searchability
Tag Text
Use Cases
Tag Text
Industries
Tag Text
Resources
Blog
Tag Text
Events
Customer Stories
Tag Text
Support
Help Center
Tag Text
Contact Support
Tag Text
Log In
Tag Text
Company
About
Tag Text
Careers
Tag Text
Security
Tag Text
Legal
Tag Text
Pricing
Tag Text
Partners
Tag Text
connect
Contact
Tag Text
LinkedIn
Tag Text
YouTube
Tag Text
Discord
Tag Text
X
Tag Text
Facebook
Tag Text
Popular
Approvals matrix
Tag Text
BPMS
Tag Text
Budgeting process
Tag Text
CapEx approval
Tag Text
CapEx automation
Tag Text
Document approval
Tag Text
Task automation
Tag Text
workflow
Overview
Tag Text
Services
Tag Text
Industries
Tag Text
Departments
Tag Text
Resources
Blog
Tag Text
Events
Customer Stories
Tag Text
Support
Help Center
Tag Text
FAQ
Tag Text
Troubleshooting
Tag Text
Contact Support
Tag Text
Company
About
Tag Text
Careers
Tag Text
Security
Tag Text
Legal
Tag Text
Pricing
Tag Text
Partners
Tag Text
connect
Contact
Tag Text
LinkedIn
Tag Text
YouTube
Tag Text
Discord
Tag Text
X
Tag Text
Facebook
Tag Text
DWS api
PDF Generator
Tag Text
Editor
Tag Text
Converter API
Tag Text
Watermark
Tag Text
OCR
Tag Text
Table Extraction
Tag Text
Resources
Log in
Tag Text
Help Center
Tag Text
Support
Tag Text
Blog
Tag Text
Company
About
Tag Text
Careers
Tag Text
Security
Tag Text
Pricing
Tag Text
Legal
Privacy
Tag Text
Terms
Tag Text
connect
Contact
Tag Text
X
Tag Text
YouTube
Tag Text
Discord
Tag Text
LinkedIn
Tag Text
Facebook
Tag Text

Copyright 2025 Nutrient. All rights reserved.

Thank you for subscribing to our newsletter!

We’re thrilled to have you join our community. You’re now one step closer to receiving the latest updates, exclusive content, and special offers directly in your inbox.

This builtin is not currently supported: DOM

PSPDFKit is now Nutrient. We've consolidated our group of trusted companies into one unified brand: Nutrient. Learn more

This builtin is not currently supported: DOM

PSPDFKit is now Nutrient. We've consolidated our group of trusted companies into one unified brand: Nutrient. Learn more

This builtin is not currently supported: DOM

New Feature Release. Tap into revolutionary AI technology to instantly complete tasks, analyze text, and redact key information across your documents. Learn More or View Showcase

This builtin is not currently supported: DOM

Aquaforest and Muhimbi are now Nutrient. We've consolidated our group of trusted companies into one unified brand: Nutrient. Learn more

This builtin is not currently supported: DOM

Integrify is now Nutrient. We've consolidated our group of trusted companies into one unified brand: Nutrient. Learn more

This builtin is not currently supported: DOM

Join us on April 15th. Join industry leaders, product experts, and fellow professionals at our exclusive user conference. Register for conference