Secrets management is keeping every key, token and password your app runs on out of its code and browser bundle, in one store, rotated and revocable. OWASP’s cheat sheet is the reference list. Of the 21 third-party apps I audited in June and July 2026, 6 shipped a real secret. These nine controls are the order for one app.
The secrets management best practices that matter for one app
Secrets management for one app is nine controls: no private key in the browser, a scanned and rotated repository history, server-only admin keys, separated environments, third-party calls behind your own auth, a rehearsed rotation runbook, spend alerts on every metered service, provider accounts the founder owns, and reviewed platform defaults.
Those 21 apps were a selected set of third-party projects I audited, not a random sample, so 6 of 21 describes that group and is not a rate for AI-built apps in general. Across the same 21, the Secrets & Credentials pillar averages 84.4 out of 100, ranked best of the 12 pillars in those audits. So this is the area the audited apps handled best, even though six of them still shipped a real secret. In production hardening, the area sits between who can log in and what the app accepts, and it holds 9 of the 123 deliverables.
None of it needs a security team. Secrets management for small teams starts with the host’s own store and one person who owns every provider account. Most of the work lands on whoever writes the code, so this is also secrets management for developers: each row names a value and the one place it may live.
| Control | What it is | Why it matters | Deeper page |
|---|---|---|---|
| 1. No private credential in the browser | Remove all private secrets from frontend code and downloadable bundles, relocating their use to server-side code | Exposed private credentials can let others access services using your permissions | API keys exposed on frontend |
| 2. History scanned, hits rotated | Scan Git history for committed secrets and rotate every exposed credential found | Deleting a secret from the latest commit leaves earlier copies accessible | secret scanning |
| 3. Admin keys on the server only | Verify service-role and administrative keys are used exclusively in protected server environments | Administrative keys can bypass the data protections intended for ordinary users | Same page as control 1 |
| 4. Separated environments | Separate development, staging, and production variables, databases, and keys; document the configuration inventory | Testing with live credentials can affect real customer data and transactions | environment variables security risk |
| 5. Paid APIs behind your auth | Move private AI, email, SMS, and other service keys server-side and implement usage caps | Abused endpoints can consume paid services on your account | cap monthly usage on a metered API |
| 6. Rotation runbook | Document how to rotate each key, update its dependents, verify the change, and recover from a failed rotation | An urgent rotation becomes harder when nobody knows which services depend on a key | how to rotate API keys safely |
| 7. Spend alerts | Configure spend or usage alerts for every metered API, using provider alerts or application-side measurement | Unexpected consumption can continue unnoticed until the next invoice | Same page as control 5 |
| 8. Founder-owned accounts | Move every service the product depends on (database, hosting, payments, email, AI, domain) into an account the founder owns, with the founder as the owner role, billing in the founder’s name, and any previous builder removed | AI-built apps are often wired to accounts the builder created. The business does not control what it does not own. | developer owns our hosting account |
| 9. Reviewed platform defaults | Review and harden the settings of every managed service in the stack: auth policies, storage access rules, privileged keys kept server-side, and a plan tier adequate for backups and recovery | Managed platforms ship permissive defaults so that prototypes work. Those defaults are what leaks data in production. | what are insecure defaults |
The guides that rank for this term mostly give the same general list: never hardcode a secret, keep secrets in one place, give each reader the least access it needs, prefer short-lived credentials, rotate, encrypt, and audit access. Read top to bottom, the table is application secrets management for one codebase: the same ideas made concrete, with a test for each line. A secrets management strategy or policy for one app is these nine lines written down; control 6 below turns the policy part into three sentences you can keep.
What counts as a secret, and why the non-human ones leak
A secret is any single value that grants access on its own: an API key, a database URL with its password, a webhook signing secret, a service-role key, an OAuth client secret, a private certificate. Secrets management is keeping each one out of the code and the browser, in one store where it can be rotated and revoked.
That is the secrets management definition I work from. It also answers what secrets in code are: any of those values typed into a source file, a config file or a build setting, where every copy of the repository carries it. In cyber security terms, secrets management covers the credentials machines use, not the passwords people type at a login screen. Proper secret management is important for a plain reason: a leaked value is access, with no second factor behind it.
OWASP now tracks machine credentials as a risk category of their own. The OWASP Non-Human Identities Top 10, published as the NHI Top 10 2025, puts Improper Offboarding first, Secret Leakage second and Long-Lived Secrets seventh. For the full reference, OWASP’s Secrets Management Cheat Sheet walks the lifecycle from creation through rotation, revocation and expiration, then covers CI/CD pipelines and cloud providers. What an API key is, and how one gets issued, has its own page: what is an API key.
What goes wrong without it
How to store API keys securely comes down to where to store API keys: on the server only, in the host’s variable store, never in a client bundle or a committed file. The API key security best practices worth following are the nine controls above, not a separate list, and the vibe coding security checklist covers the whole-app checks around them. Each failure below shows what happens when one of those API key best practices is missing, with the audit number where I have one and the page that goes deeper.
A private key is in the browser bundle
You open the browser’s network tab, or the JavaScript bundle the site downloads, and find a key that should only exist on the server. Once a private credential reaches the browser, anyone who reads the bundle can use that service with your permissions. In the same audits, a real secret shipped in 6 of the 21 apps. The section on exposed API keys in a vibe coded app covers this failure in more depth. Which keys may sit in the browser at all is a narrower question: a Supabase publishable key is safe to expose, a Supabase secret key never is, and the page on API keys exposed on the frontend sorts the rest.
A secret is in git history and was never rotated
The key was deleted from the code months ago, and it still works. A delete in the newest commit does nothing to the older commits, so every earlier copy stays reachable in the history. In the same audits, three apps had a real secret permanently in git history: a webhook signing secret, a live AI-provider key, and a Stripe test key with its webhook secret.
In a multi-tenant point-of-sale app I audited, the auth provider’s webhook signing secret was committed, then “deleted” in a later commit. It stayed in history, so anyone who cloned the repository could forge signed webhook calls until the secret was rotated. The lesson I take from it: removing the line was housekeeping, and only the rotation closed the hole. If a key has already leaked, the first hour has its own checklist: API key leaked what to do. Finding every hit in the history is a job for secret scanning, which has its own page.
Staging writes to the production database
A test order charges a real card, or a test signup emails a real customer. When staging runs on live credentials, a test can reach real customer data and real transactions. I have no audit count for this one. The fastest check is to open each environment’s settings side by side and compare the database URL and the payment key: if staging and production show the same value, they are the same system with two names. Splitting them properly, down to separate databases and a written inventory, is on the page about the environment variables security risk.
A stranger runs up the AI bill
An AI or SMS bill jumps overnight with no matching jump in users. In the same audits, 12 of the 14 AI apps had a confirmed denial-of-wallet path, where a stranger or free account can burn the owner’s paid AI or compute bill without limit. That 14 is its own denominator: the third-party apps in the set that had an AI feature, not all 21. The cause is the one in the table’s control 5 row: an endpoint anyone can reach can spend on your paid services. Per-user caps, monthly ceilings and the alert that tells you before the invoice does are on the page about capping monthly usage on a metered API.
The developer who built it still owns the hosting account
You need to rotate a key and find you cannot, because the hosting, database or AI account belongs to the freelancer or agency who built the app. Builders often wire an AI-built app to accounts they created themselves, and a business has no control over an account it does not own. That makes ownership a secrets problem: a key that lives in an account the business does not own is a key the business does not control. Moving each account across and removing the builder cleanly has its own page, written for a founder whose developer still holds the keys.
The nine controls, one by one
Each control below says what it asks for, the test that proves it, and where the depth lives. Run the tests on a staging copy where you have one.
1. No private credential reaches the browser
Every private secret comes out of the frontend code and the downloadable bundle, and the code that used it moves to the server. To verify it: scan source and built assets and inspect browser traffic for private credentials. Search for each private key’s actual value as well as its variable name. Supabase’s docs note that its legacy keys are long strings beginning with eyJ, so a search for an sk- prefix alone misses them. The frontend-keys page in the table lists which keys are public by design.
2. The repository history is scanned and every hit is rotated
The whole Git history gets scanned, not only the current code, and every real credential the scan finds is rotated. To verify it: retain scan results and confirm exposed credentials have been invalidated and replacements work. The GitHub secrets best practices come down to three things: push protection on where your plan allows it, a scanned history, and every hit rotated. GitHub push protection for users is enabled by default and stops you from pushing secrets to public repositories; push protection for a repository requires GitHub Secret Protection, is disabled by default, and can be enabled by a repository administrator or an organization owner. GitHub’s Advanced Security page says Secret Protection is available for accounts on GitHub Team and GitHub Enterprise Cloud, with some features free for public repositories. So on a private repository on the Free plan, this control rests on a history scan you run yourself and the rotations that follow; the scanning tools are on the secret scanning page. Whether an AI coding assistant can read secrets already sitting in the repository is covered in GitHub Copilot security risks.
3. Administrative keys are server-only
Service-role and admin keys run only where the server protects them: an API route, a server function, a scheduled job, never code that ships to the browser. To verify it: check runtime configuration, built assets, and each code path using administrative credentials. Supabase’s API keys guide is blunt about its own: a secret key bypasses Row Level Security, so you never put one in a browser, a shipped application, or source control. Its legacy service_role key is the older version of the same key, and creating the new keys does not revoke the legacy ones, so check for both.
4. Development, staging and production are separated
Each environment gets its own variables, database and keys, and a written inventory says which value belongs where. To verify it: inspect environment mappings and confirm staging actions stay within staging services. Give staging the provider’s test-mode keys wherever a provider offers them, so a staging checkout cannot move real money. How the local .env file, the hosting dashboard and a framework’s public prefix decide what reaches the browser is in environment variables explained.
5. Third-party APIs are called from the server, behind your own auth
Keys for AI, email, SMS and other paid services live on the server, and your own route sits in front of each call with a sign-in check and a usage cap. To verify it: test unauthorized calls, per-user limits, and configured usage ceilings. Call each route that spends money with no session first, then as a signed-in user past the limit. The API security checklist covers per-user limits across every route, and the metered-usage page covers the monthly ceiling.
6. There is a rotation runbook, and it has been rehearsed
A short written document says, for each key, how to rotate it, which services need the new value, how to check the change worked, and how to back out if it did not. To verify it: rehearse rotation with a test credential and record the affected services and checks. The same document holds a secrets management policy template for one app, three sentences long. Only the founder or a named engineer creates production keys. Every key lives in the host’s store for its environment and nowhere else. Every key rotates when someone with access leaves, after any suspected leak, and on a date written next to it. The step-by-step rotation, including how to avoid downtime, is on the page about how to rotate API keys safely.
7. Every metered service has a spend alert that reaches a person
Each paid API gets a spend or usage alert, from the provider where it has one and from your own counts where it does not. To verify it: trigger a test threshold and confirm the alert reaches the designated owner. Set the test threshold low enough to fire on today’s usage, and give the provider its reporting delay before you decide the alert failed. An alert that lands in a shared inbox nobody reads has not reached a person. Caps and alerts together are on the same metered-usage page as control 5.
8. The founder owns every provider account
Database, hosting, payments, email, AI and the domain each sit in an account the founder owns, with the founder in the owner role, the bill in the founder’s name, and any previous builder removed. To verify it: produce an inventory listing each provider, the owning account, the owner role holder, and the date the previous builder’s access was removed. Keep that inventory next to the rotation runbook, since the two answer the same question from different ends: who can change a key, and what breaks when they do. The move itself, provider by provider, is on the account-ownership page linked in the table.
9. Managed-platform defaults are reviewed and recorded
Each managed service in the stack gets a settings review and a hardening pass, covering its auth policies, its storage access rules, where its privileged keys live, and whether its plan tier is adequate for backups and recovery. To verify it: record the before-and-after settings for each managed service, naming each risky default and its new value. The record matters as much as the change, because the next person to touch the dashboard needs to know which settings were chosen on purpose. The common risky defaults, platform by platform, are on the insecure defaults page.
Where your stack already keeps secrets
Secrets for one app belong in the host’s own variable or secret store, scoped per environment, and nowhere else: not in a committed file, not in the client bundle, not in chat. Every host in the table below has such a store, so the first control needs no new tool.
The store names come from each platform’s own docs; the last column is my reading of what never belongs there.
| Platform | Its secret or variable store | What never goes there |
|---|---|---|
| Vercel | Environment variables per environment, encrypted at rest; a variable saved as Secret is write-only after saving | A private key under a framework’s public prefix |
| Netlify | Environment variables, which can be marked “Contains secret values” for the Secrets Controller | A secret committed in the repository |
| Supabase | Edge Function Secrets, set in the Dashboard or with supabase secrets set | The secret or service_role key, in any client code |
| Firebase | Cloud Functions secrets, stored in Google Cloud Secret Manager and set with firebase functions:secrets:set | Sensitive values in the functions .env file |
| Railway | Service variables and shared variables; a sealed variable is never visible in the UI nor retrievable via the API | A production key left unsealed for every teammate to read |
| Render | Environment variables, secret files and environment groups | A secret file committed next to the code |
| Heroku | Config vars, which persist across deploys and app restarts | A value hard-coded in the app as a fallback |
| GitHub Actions | Repository, environment and organization secrets | A secret printed to a workflow log |
| Docker | Docker secrets, only available to swarm services, not to standalone containers | A secret baked into a Dockerfile or image layer |
| Kubernetes | Kubernetes Secrets, stored unencrypted in etcd by default | A Secret manifest with real values committed to Git |
| Ruby on Rails | Encrypted credentials in config/credentials.yml.enc, unlocked by config/master.key or RAILS_MASTER_KEY | The master key, in the repository |
| AWS | Secrets Manager; Parameter Store SecureString for encrypted configuration values | A long-lived access key where a role could do the job |
| Google Cloud | Secret Manager | A service account key file in the repository |
| Azure | Key Vault | A connection string hard-coded in the app |
Kubernetes secrets management needs one step the others do not: the Kubernetes Secrets page warns that Secrets are, by default, stored unencrypted in the API server’s underlying data store, etcd, and that anyone with API access can retrieve or modify one. Docker secrets management depends on swarm mode, as the Docker row says. Rails credentials are the only store in the table designed to be committed. Rails encrypted credentials can be committed because the file is encrypted, as long as the master key is kept safe and never committed.
Cloud secrets management works the same way at a larger scale, with one managed service per cloud. For AWS secrets management, AWS’s own Parameter Store page recommends Secrets Manager for database credentials, API keys and tokens, and SecureString for configuration values that need encryption. Azure Key Vault for secrets management is Microsoft’s equivalent; its overview describes it as a place to securely store and tightly control access to tokens, passwords, certificates, API keys and other secrets. For what Google protects on a Firebase project and what you configure yourself, see is Firebase secure.
A framework’s public prefix can still ship a value from any of these stores to the browser. The environment variables article linked under control 4 covers that, and its host scopes and apply rules table shows how each host applies a changed value.
Secrets in CI and in infrastructure code
CI/CD secrets management follows the same rule: pipeline secrets live in the CI provider’s own store, never in the workflow file. For GitHub secrets management, GitHub Actions lets you create secrets at the repository, environment and organization levels. On GitHub Free, environment secrets are only available in public repositories and organization-level secrets are not accessible by private repositories, so a free private repository uses repository secrets. GitLab secrets management adds a distinction worth knowing: GitLab’s CI/CD variables are always available in jobs, while external secrets from a provider such as HashiCorp Vault or AWS Secrets Manager must be requested by a job explicitly.
In DevOps secrets management, the pipeline is one more runtime: it reads a value when a job runs and should never print it. GitHub’s docs say to mask any sensitive value that is not a GitHub secret with ::add-mask::, so it is redacted from logs. Terraform secrets need their own care: HashiCorp’s docs say that if you add secret values directly to your configuration, Terraform stores them in its state and plan files, and a local state file is plaintext, so keep it out of Git. Pipeline permissions and scanning are covered in securing the pipeline.
Short-lived credentials beat long-lived keys
A short-lived credential expires on its own; a long-lived key stays valid until someone revokes it. AWS Security Token Service issues temporary, limited-privilege credentials, and OIDC federation lets a deploy platform get them without a stored key, so my working rule for one app is no permanent cloud key where a role can do the job.
An AWS STS example for one app: a nightly job assumes a role with the AssumeRole call and gets back an access key ID, a secret access key and a security token, valid from 15 minutes up to the role’s maximum session duration, after which they stop working. The AWS Security Token Service reference covers the rest of STS in AWS, including the other calls that issue temporary credentials.
Vercel’s OIDC federation does the same for deployments: Vercel puts a signed OIDC token in the VERCEL_OIDC_TOKEN environment variable, and AWS, Google Cloud and Microsoft Azure can exchange it for short-lived credentials, so no long-lived cloud key has to sit in Vercel’s environment variables. Vercel lists it as available on all plans. On EC2, IMDSv2 is session-oriented and IMDSv1 is a plain request/response method; by default an instance accepts either, and you can configure it to accept only IMDSv2.
Credentials on a developer laptop
On a laptop, AWS credentials are stored where aws configure puts them. When you set up AWS CLI credentials that way, the CLI writes them to a local file named credentials in the .aws folder of your home directory, and the AWS CLI configuration and credential files page says these are plaintext files. So the AWS credentials file is readable by anything that can read your home folder, and a project’s .env file is a second copy on the same disk. A profile that names an IAM role makes the CLI call AssumeRole and run its commands on temporary credentials, but it still needs other credentials, such as a source profile, to make that call. For the AWS CLI with MFA, AWS documents the get-session-token call: an MFA-enabled IAM user submits a code from their MFA device and gets temporary credentials back. Keep production keys off the laptop entirely, so a lost machine means revoking one developer’s access, and the app’s own keys stay where they are.
Do you need a dedicated secret manager?
A dedicated secret manager is worth it, by my working rule, when more than one runtime or more than one team reads the same secret. One app on one host is usually neither. The host’s store plus a rotation runbook covers the nine controls; AWS Secrets Manager charges per secret per month when you outgrow it.
What a secrets manager is, as I read the vendors’ docs: a service that keeps values encrypted, releases them to a runtime on request and records each read. The secrets management tools in the table are examples, not a ranking, and the “what it adds” and “fits when” columns are my reading.
| Option | What it adds | Cost basis | Fits when |
|---|---|---|---|
| The host’s own store | Nothing new to run; the value lives where the app runs | Part of the host plan | One app on one host |
| AWS Secrets Manager | Automatic rotation, encryption and a central audit trail | $0.40 per secret per month, $0.05 per 10,000 API calls | The app already runs on AWS, or several services read one secret |
| Google Secret Manager | A managed store that Firebase functions already use | Free each month: 6 active secret versions, 10,000 access operations, 3 rotation notifications; then per version and per operation | The app runs on Firebase or Google Cloud |
| HashiCorp Vault | A secrets engine you run yourself, or HashiCorp’s hosted HCP Vault | Self-hosted under the Business Source License; HCP pricing not stated here | Several teams or clouds, and someone to operate it |
| Doppler | One set of values synced out to several hosts | Developer plan free for 3 users | A small team feeding several hosts |
| Infisical | Secrets pulled from one place by each host, pipeline and service | Free plan with 5 identities and unlimited projects | A few people and a few pipelines on one project |
Prices checked September 28, 2026, on AWS Secrets Manager pricing, Google Secret Manager pricing and Doppler’s and Infisical’s own pricing pages. AWS Secrets Manager pricing is the per-secret, per-call line in the table; Google’s free allotment is counted per billing account and resets every month. Secrets manager pricing matters less than it looks for one app: the host’s store costs nothing extra, and the cost question only starts once a second runtime needs the same value.
If you want a self-hosted secrets manager, HashiCorp Vault secrets management is one route: run Vault on your own servers, or use HashiCorp’s hosted HCP Vault. For open source secrets management, read the license before you pick: HashiCorp’s own repository puts Vault 1.15.0 and later under the Business Source License, which allows production use except offering Vault to third parties, hosted or embedded, in competition with IBM’s paid versions.
AWS KMS vs Secrets Manager is a question of what each holds: KMS creates and controls the keys used to encrypt and sign your data, and Secrets Manager stores the secret values themselves. That is the whole difference between secrets management and key management for one app. The encryption key management best practices past that line belong with database encryption, which has its own page.
Sharing a credential with a teammate
How to share API keys securely starts with what not to do: never by email or chat. OWASP’s NHI list names secrets sent over public chat applications among those that become susceptible to exposure. For secret key sharing inside a team, use a password manager for business with shared vaults, such as 1Password or Bitwarden, or a one-time secret link that stops working once opened. Better, as my working rule: the teammate gets their own credential from the provider wherever it allows one, so revoking one person never breaks the app.
How to verify the whole area in an afternoon
Verifying this area takes nine tests and, as my working estimate for a small app, about one afternoon: grep the built bundle, check admin key paths, scan the git history, read the environment mappings, call a third-party route without a session, trip a spend alert, rotate one test credential, write the provider inventory, and record platform settings.
Run them in this order, on staging where you can. Each item points back to its control above, where the exact test sits. For every item, write down the date, the command or screen you used, and the result, including a clean result.
- 01 Built bundle and browser traffic: search the production build and the network tab for every private key value, including legacy Supabase keys that begin with eyJ (control 1).
- 02 Admin key paths: list every code path and runtime setting that uses a service-role or admin key, and confirm each one runs on the server (control 3).
- 03 History scan: run a secret scanner over the whole Git history and confirm every real hit is dead and its replacement works (control 2).
- 04 Environment mappings: compare each environment database URL and payment key, then run one staging action and confirm it stayed in staging (control 4).
- 05 Third-party routes: call each route that spends money with no session, then as a signed-in user past its limit (control 5).
- 06 Spend alert: set a low test threshold, wait out the provider reporting delay, and confirm the named owner received it (control 7).
- 07 Rotation rehearsal: rotate one test credential with the runbook and note every service you had to touch (control 6).
- 08 Provider inventory: list each provider, the owning account, the owner, and when the previous builder lost access (control 8).
- 09 Managed-platform settings: write down each risky default and its new value, before and after (control 9).
When all nine pass, the rest of the app still has its own list: the full production readiness checklist covers the other areas the same way.
Where the sprint stops
In the sprint, your app’s current framework and hosting setup are the starting point, and components are refactored or replaced where the production work requires it. Formal third-party certifications and independent audit opinions are separate from these engineering deliverables. Hosting, paid tools and API usage remain in your accounts, and we explain any required third-party costs before enabling them.
Where the sprint does this
Area 2 of the Production Hardening Sprint is these nine controls, 9 of its 123 deliverables. We deliver each one as its section above describes and check it with the test quoted there. Every result goes into the production readiness report, which accounts for all 123 IDs, keeps failures visible until resolved and explains genuine non-applicable items. The deliverables, word for word, are in area 2 of the published scope.
Common questions about keeping keys and credentials safe
What are the best practices for secrets management?
For one app, the best practices are nine habits: private keys stay out of the browser, the Git history is scanned and every hit rotated, admin keys run only on the server, each environment has its own keys, paid APIs sit behind your own sign-in, a rotation runbook has been rehearsed, spend alerts reach a person, the founder owns every provider account, and platform defaults are reviewed.
Which secrets management tool is the best?
No single tool is best in general. For one app on one host, the host’s own secret store is the right tool; a dedicated manager such as AWS Secrets Manager, Google Secret Manager, HashiCorp Vault, Doppler or Infisical earns its place once more than one runtime or team reads the same secret, which is my working rule rather than a vendor’s.
Is there a free secret manager?
Yes. The variable or secret store that comes with your hosting plan costs nothing extra, as I read the hosts’ docs, and Google Secret Manager gives 6 active secret versions and 10,000 access operations a month free per billing account. Doppler’s Developer plan is free for 3 users, and Infisical’s Free plan covers 5 identities.
Where should secrets be stored?
In the store your host provides, one set of values per environment: Vercel’s or Netlify’s environment variables, Supabase Edge Function Secrets, Heroku config vars, or the cloud’s secret manager if the app runs on AWS, Google Cloud or Azure. Never in the repository, the client bundle or a chat thread.
How does a secret manager work?
Your app authenticates to the manager when it runs, asks for a value by name, and gets it back decrypted; the manager checks that the caller is allowed to read it and records the request. That is my reading of the vendors’ docs. Rotation then happens in one place: change the value in the manager, and the next read picks up the new one.
How much does Secrets Manager cost per month?
AWS Secrets Manager costs $0.40 per secret per month plus $0.05 per 10,000 API calls, as AWS’s pricing page showed on September 28, 2026. AWS’s own worked example on that page, 15 secrets for a production-scale web application, comes to $6.00 a month for the secrets before API calls, and new AWS customers can apply up to $200 in Free Tier credits to it.
The checks in this guide show you where the app is open. The sprint below closes those gaps, tests the result and writes the evidence down.
Built it with AI. Now it has to hold up for real customers.
The Production Hardening Sprint takes the app you already have and builds the production foundation underneath it. Authentication and access rules, payments that stay consistent, error handling, monitoring, backups, automated tests and a documented handover. Our engineers work inside your existing codebase for ten working days. All 123 deliverables are included, and you get the evidence for each one.
See the Production Hardening Sprint →
$2,500 fixed price · 10 working days · One codebase